How to get a set number of rows from a ResultSet - java

I only need the two most current items in a result set and was wondering what the best way to do that would be without a break. I realize that rs.next() returns true or false and tried to stop it with a counter but that failed. I have this at the moment:
while(rs.next()){
String name = rs.getString("name");
String startTime = rs.getString("starting_time");
String endTime = rs.getString("ending_time");
String date = rs.getString("directory");
String loc = rs.getString("location");
htmlBuilder.append("<li><a href='public/committees/calendar'>"+ name+"<br>");
htmlBuilder.append(date +" "+startTime+" - "+endTime+"</a> <!-- Link/title/date/start-end time --><br>");
htmlBuilder.append("<strong>Location: </strong>"+loc+"<br>");
htmlBuilder.append("</li>");
}
html = htmlBuilder.toString();
As you can tell, this returns everything from the ResultSet but I only need the first two entries.
Here is my correct query:
SELECT to_char(to_date(to_char(x.starting_date), 'J'),'mm/dd/yyyy') as start_date, to_char(to_date(to_char(x.ending_date), 'J'),'mm/dd/yyyy') as end_date, to_char(to_date(to_char(x.starting_date), 'J'),'yyyy-mm-dd') as directory, x.starting_time, x.ending_time, x.description, x.description as location, x.name, x.short_name, x.add_info_url, x.contact_name, x.contact_info FROM calitem x, calendar x, calitemtypes x WHERE x.calendar_id = x.calendar_id AND x.short_name LIKE ? AND x.style_id = 0 AND x.starting_date > to_char(sysdate-1, 'J') AND x.item_type_id = x.item_type_id AND ROWNUM <= 3 ORDER BY to_date(to_char(x.starting_date), 'J')
Adding the rownum attribute worked perfectly and the query was ordered before return. Thanks for the help

You should limit the query to return only the two most current rows. This can by achieved by a LIMIT clause (exists in MySQL, not sure about other DBs) and an ORDER BY clause.
There is not need to add an index that would count the rows returned by the ResultSet.

Related

Select * from SQLite TempTable not working properly

I have this small piece of code, the scope is:
In the outter while: I calculate a "min" number (selected from the tempTable)
In the inner while: I "Select * from (tempTable) where (some conditions)" (im completly sure there is more than 1 row that matches these conditions) and then i update the min in each row selected (whithin other aspects not relevant)
The inner while is conditioned by rs.next() which (as it does in other parts of my code) it should iterate through every row that matches the condition ("Select * from (tempTable) where (some conditions)")
Basically the program should work as: getting a "min" value, then proceed to update each row with equal "min" and "min" = "min" + 1. So in the next iteration of the outter while the "min" should be 1 more.
Instead, what it does is: get "min" value, then update ONLY the first row that matches that min value and goes back to the outter while(which calculates the min again). In the end, the output is rather the same and it kinda works, but I would really appreciate if it worked as I intended to match other aspects of the program.
I think the problem comes from doing a select * from a TEMPtable which for some reason returns only 1 row (i've been investigating but couldnt find other people with the same issue, so i don't really know). As I mentioned, there is other parts of my code where I do the same select * NORMALtable and the ResultSet.Next() works as intended.
while( total_tfgs > 0 ) {
int tfgs_round = 0;
min = prepareStatement.executeQuery("SELECT MIN("+ PROFESORES_COL_TFGS +") FROM TEMP_TABLA_PROFESORES WHERE " + PROFESORES_COL_OBLIGA + " = 'SÍ'").getInt(1);
ResultSet rs = prepareStatement.executeQuery("SELECT * FROM TEMP_TABLA_PROFESORES WHERE " + PROFESORES_COL_TFGS + " = '" + min + "' AND " + PROFESORES_COL_OBLIGA + " = 'SÍ'");
while(rs.next()) {
prepareStatement.executeUpdate("UPDATE TEMP_TABLA_PROFESORES SET PROFESORES_COL_TFGS = PROFESORES_COL_TFGS + 1 WHERE PROFESORES_COL_ID = '" + rs.getInt(1) + "'");
tfgs_round = tfgs_round + 1;
}
total_tfgs = total_tfgs - tfgs_ronda;
}
Here i place code where it works as i want it to work:
Statement statement = con.createStatement();
ResultSet rsA = statement.executeQuery("SELECT * FROM " + TABLA_ALUMNOS);
while(rsA.next()) {
String idA = String.valueOf(rsA.getInt("ALUMNOS_COL_ID"));
String dniA = rsA.getString("ALUMNOS_COL_DNI");
String nombreA = rsA.getString("ALUMNOS_COL_NOMBRE");
String dataA[] = {idA, dniA, nombreA};
DefaultTableModel tblModel = (DefaultTableModel) table_Alumnos.getModel();
tblModel.addRow(dataA);
table_Alumnos.setModel(tblModel);
}
PD: while redacting this i changed some variables to english (in the first code snipet) so it would be more legible(tfgs_round,total_tfgs), so if there is some misspell or something, thats not the problem. Please focus in the ResultSet select * from TEMP_TABLE (which i didnt change)
Thank you in advance for any help you can provide.
I would not call executeUpdate within the loop that is reading the ResultSet. That means you are using the statement for a second query while it is still involved in the first query. I would finish the first query entirely, close the ResultSet and then perform the update separately. If you really need to do an update while reading a ResultSet, I would build a new statement for it.

Android sqlite - how to calculate the difference between 2 REAL entries in sqlite?

In Android/Java, I am trying to compute and store the difference between 2 values in sqlite when one value is entered.
My table looks like this:
When weights are added/stored in the table in the column 'Weight', the column 'Diff_Weight' shall receive "Weight(N) - Weight(N-1)". Example: the last cell of Diff_Weight (row 6) = 88.0 - 55.2 = 32.8. // Row 5 shall get '-0.7' etc. Their type is REAL (col Weight & col Diff_Weight).
This 32.8 should be calculated and added at the same time when 88.0 is added to the table.
So far, I have read lots of tutorials and can't figure how to proceed. (My code to create and insert in the DB is fine, but reading is somehow more complex).
My code to read the entry is very bad because I don't see how to set it up:
public Bouble getData() {
String selectQuery= "SELECT * FROM " + TABLE_NAME2 + " ORDER BY COL_4 DESC LIMIT 1";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(TABLE_NAME2, null);
result2 = Double.valueOf(cursor.getString(cursor.getColumnIndex("Weight")));
result1 = Double.valueOf(cursor.getString(cursor.getColumnIndex("Weight")-1));
insertdata(result2-result1); //insert in row 6 of Diff_Weight
return
}
Can anybody help there?
If that is unclear, I was needing some help for the sqlite command AND the java to get the difference result.
Simplistically you can get the data by joining to the same table
SELECT a.id, a.weight, b.weight, (b.weight - a.weight) FROM TABLE_NAME2 a
join TABLE_NAME2 b on (b.id = a.id + 1);
One way is to use the lag() window function to get the value of the previous row (As ordered by id; using timestamps would be better but between splitting up the date and time into different columns and not using a date format that can be meaningfully sorted, this is easier.):
SELECT id, weight,
round(coalesce(weight - lag(weight, 1) OVER (ORDER BY id), weight), 1) AS diff_weight
FROM example
ORDER BY id
which gives
id weight diff_weight
---------- ---------- -----------
1 22.0 22.0
2 22.2 0.2
3 55.0 32.8
4 55.9 0.9
5 55.2 -0.7
6 88.0 32.8
You can make a view of this query use that like a normal table if you like. Generating the differences dynamically like this has the advantage that if an existing weight value changes, everything that depends on it doesn't have to be updated.
ok, after a long search, here is a possible result (sqlite + java):
first, you need to query the last row of the table...
...and handle the case if there is no row in your table (blank or new table)
then you must query the 'Weight' value from the known column 'Weight' (Y) and the row with ID you already have (X)
and when you have your value (last_weight), you need to write the difference (weight-last_weight) in the column 'Diff_Weight'.
Here is the code:
SQLiteDatabase db = this.getWritableDatabase();
//query the last row of the table
Cursor cursor = db.rawQuery("SELECT ID FROM TABLE_NAME2 ORDER BY ID DESC LIMIT 1", null);
cursor.moveToLast();
int lastID;
//handle the case if there is no row in your table
try {
lastID = cursor.getInt(0);
} catch (Exception e) {
lastID = 0;
}
Double lastWeight = 0.0;
//query the 'Weight' value
if (lastID >= 1) {
Cursor cursor2 = db.rawQuery("SELECT Weight FROM TABLE_NAME2 WHERE ID=" + lastID, null);
if (cursor2.moveToFirst()) { //this is boundary otherwise 'lastWeight' doesn't get the value
lastWeight= cursor2.getDouble(0);
}
} else {
lastWeight = 0.0;
}
//write the difference in the Diff_Weight column (=COL_5)
ContentValues cValues2 = new ContentValues();
//add your data in COL_1 to COL_4 here...
cValues2.put(COL_5, weight - lastWeight);
long id2 = db.insert(TABLE_NAME2, null, cValues2);
... And so you get the red figures in the column Diff_Weight from the table photo in the question.

noob, java spring autowired hibernate mysql query, is this right?

I'm working on a small program that lists local train stops in a numbered list then asks for the user to type the number of the station that they wish to see the next arrival time for.
The problem I have is I don't think the MySQL query is correct to retrieve the arrival time. The list returns empty. Using jdbc previously, this query worked fine:
"SELECT arrival_time FROM stop_times WHERE stop_id = '"
+ myStation.getID()
+ "' AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
And the current hibernate query:
public List<String> getArrivals() {
sessionFactoryBean.getCurrentSession().beginTransaction();
String sql = "SELECT arrival_time FROM stop_times WHERE stop_id = '"
+ myStation.getID()
+ "' AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
Query query = sessionFactoryBean.getCurrentSession()
.createSQLQuery(sql)
.addEntity(Station.class);
List<String> arrivals = query.list();
sessionFactoryBean.getCurrentSession().getTransaction().commit();
return arrivals;
}
Called from this method and where I get IndexOutOfBoundsException:
public String getNextArrival(int user_input) {
getStationName(user_input);
List<String> arrivals1 = arrival.getArrivals();
System.out.println(arrivals1);
System.out.println(arrivals1.size());
String arrivalTime = arrivals1.get(user_input);
return convertTime(arrivalTime);
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0,
Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at com.moeller.code.Stops.getNextArrival(Stops.java:73)
Line 73 String arrivalTime = arrivals1.get(user_input);'
The DataBase is stored locally.
There are several problems with this.
First, the query does not use parameters, which means you will likely make this mistake elsewhere where it will be a danger. You have to pass on variables like this:
String sql = "SELECT arrival_time FROM stop_times WHERE stop_id = ?"
+ " AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
Query query = sessionFactoryBean.getCurrentSession()
.createSQLQuery(sql)
.addEntity(Station.class);
query.setParameter(1, myStation.getID());
See the question mark? That is a positional parameter. You can also use named parameters.
String sql = "SELECT thing FROM table WHERE column1 LIKE :ptrn";
...
query.setParameter("ptrn", "%that%");
Notice how inside the query the parameter starts with :, but it does not when calling setParameter.
This way of safely inserting parameters is called using "Prepared Statements", or "Parameterized Queries". Find a quick tutorial on them, they are very important.
Secondly, in getNextArrival you forget to check if the list has that many elements.
if (arrivals1.size() <= user_input) {
return null;
}
Of course then you have to be careful when it returns a null to the function where it's used.
You are using a wrong method for the List.
when yo use List.get(param) param should be the position that you are looking for, no the userInput.
you need loop the list and compare each position of the list with the user input.
best Regards

select JDBC query not retrieving records in order

I am trying to fetch records from oracle db. I have a select query which has an order by clause implemented. Now when I fire the query on the toad i get the results in correct order. i.e the order of the records at 10:00 AM is like
Record 1, Record 2,Record 3 and at 10:05 its Record 1, Record 2, Record 3. This is what i need.
Now when iam fetching it through java code, JDBC . I try to iterate the resultset, but here at 10:05 am I am getting the order like Record 2, Record 1, Record 3. Due to this when i am adding the records to the arraylist the order is not mantained.
I dont want to sort the records of arraylist after adding.
Can someone please let me know why using jdbc the records are not fetched in the order we can see using toad ?
Sample code
try{
List<TestObjVO> testResults = new ArrayList<TestObjVO>();
double statusValue = 0;
//Connection code
pstmt = conn.prepareStatement(QUERY);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
testObj = new TestObjVO();
String date = rs.getString(1);
String status = rs.getString(2);
String svc_nm= rs.getString(3);
if("SUCCESS".equalsIgnoreCase(status)){
statusValue = 1;
}else if("ERROR".equalsIgnoreCase(status)){
statusValue = -1;
}
testObj.setTime(date);
testObj.setStatus(statusValue);
testObj.setSvc_nm(svc_nm);
testResults.add(testObj);
}
SELECT query
SELECT to_char(PROBING_DATE,'DD-MM-YYYY HH24:MI:SS') AS PROBING_DATE, STATUS, SERVICE_NAME FROM TABLE_NAME WHERE PROBING_DATE >= (sysdate-30/1440) ORDER BY PROBING_DATE,SERVICE_NAME
Table
create table TABLE_NAME(
probing_date TIMESTAMP(6) not null,
status VARCHAR2(8) not null,
service_name VARCHAR2(128) not null
)
Change your select to something like this:
SELECT to_char(PROBING_DATE,'DD-MM-YYYY HH24:MI:SS') AS PROBING_DATE_STR,
PROBING_DATE,
STATUS,
SERVICE_NAME
FROM TABLE_NAME
WHERE PROBING_DATE >= (sysdate-30/1440)
ORDER BY PROBING_DATE,SERVICE_NAME;
Note there's an extra field returned and is the raw TIMESTAMP field.

Using LIKE to search for Date with year and month only

I want to filter my table to show records by month so i make a textboxes for the user input. Now i dont know if my query is correct. I dont have any error but also doesnt have any results. I use LIKE because i dont have specific day provided. Can someone suggest a better way?
ConnectToDatabase conn = null;
conn = ConnectToDatabase.getConnectionToDatabase();
String query = "Select * from inventoryreport where InDate LIKE "+txtYear.getText()+""+ txtMonth.getText()+"";
conn.setPreparedStatement(conn.getConnection().prepareStatement(query));
conn.setResultSet(conn.getPreparedStatement().executeQuery());
java.sql.ResultSetMetaData metaData = conn.getResultSet().getMetaData();
int columns = metaData.getColumnCount();
for (int i = 1; i <= columns; i++) {
columnNames.addElement(metaData.getColumnName(i));
}
LIKE it's wrong choise becouse your db doesn't use index and will be slow (and doesn't work).
The query is like this:
SELECT * FROM inventoryreport WHERE YEAR(Date_column) = 2014 AND MONTH(Date_column) = 3;
So your code is:
String query = "Select * from inventoryreport where YEAR(InDate) = " +txtYear.getText()+" AND MONTH(InDate) = "+ txtMonth.getText();
I think it is a small mistake in the date format:
Your format : YYYYMM (no seperation symbol)
Right format: YYYY-MM-DD (with a '-' to seperate)
I think
String query = "Select * from inventoryreport where InDate LIKE "+txtYear.getText()+"-"+ txtMonth.getText()+"-00";
should fix it, if your database only includes monthly exact values.
Otherwise you should use
Select * from inventoryreport where InDate BETWEEN '2014-03-18' AND '2014-03-20'
A SQL query can take advantage of indexes when a column in not surrounded by a function. The following where clause would allow the use of indexes:
SELECT *
FROM inventoryreport
WHERE Date_Column >= str_to_date(concat_ws('-', txtYear.getText(), txtMonth.getText(), '01'), '%Y-%m-%d') and
Date_Column < adddate(str_to_date(concat_ws('-', txtYear.getText(), txtMonth.getText(), '01'), '%Y-%m-%d'), interal 1 month)
Although more complicated, all the manipulations are on constants, so the query engine can still take advantage of an index on Date_Column.

Categories

Resources