Java Sql 'select sum' giving incorrect value - java

I'm not experienced in java and I'm stuck with this problem and couldn't figure out the cause for weeks. I have a sql query that selects, counts and groups by the column "name". Next in the 'while(rs.next())' I am trying to select the sum of two other columns, a column named "kolicina" and a column named "cena" here is the code of that method:
public ArrayList<Artikli> getSum(String date){
ArrayList<Artikli> list = new ArrayList<Artikli>();
String query = "select name, count(name) as count from izvestaj where dateZat = '"+date+"' group by name";
try {
rs = st.executeQuery(query);
while(rs.next()){
Artikli art = new Artikli();
art.name = rs.getString("name");
String q = "select sum(kolicina) as total from izvestaj where name = '"+art.name+"' and dateZat = '"+date+"'";
rs2 = st2.executeQuery(q);
while(rs2.next()){
art.kolicina = rs2.getInt("total");
}
String q1 = "select sum(cena) as total1 from izvestaj where name = '"+art.name+"' and dateZat = '"+date+"'";
rs3 = st3.executeQuery(q1);
while(rs3.next()){
art.cena = rs3.getInt("total1")/rs.getInt("count");
}
list.add(art);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
The problem is that the second query returns the correct sum of the column kolicina, but the third query returns result set with the sum multiplied by the count number (from the first query... That's why i divide it with the count in the end), but still, it doesn't actually return the correct ammount. Column "cena" is actually price in english, so it seems that it's making some average price and than multiplies it with the number of records... I double-checked the insert queries and they are fine, so I am sure i insert the correct values. Any help appreciated.

Instead of issuing two distinct queries per name, just issue
select name,
sum(kolicina) as total,
sum(cena) as total1
from izvestaj
where name is not null and
dateZat = ?
group by name
(re. the questino mark : read up on PreparedStatements and how to set up parameterized queries in order to protect yourself properly against SQL injections.)
(I think you can even skip the first query as its results will also be contained in this query's results.)

Related

How do you access the value of a DQL count() query in Java Program

I want to get to the value I am finding using the COUNT command of DQL.Normally I enter the column name I want to access into the getInt() getString() method. What I'm supposed to do when there is no specific colomn name.
{
String query = "select count(*) as count from dm_user;";
return query;
}
Code to fetch the result
{
IDfCollection total = dql.execute(session, IDfQuery.DF_READ_QUERY);
while (total.next()){
cint = total.getInt("count");
}
Tomcat Result
DfException:: THREAD: http-8080-2; MSG: [DM_QUERY_E_SYNTAX]error: "A Parser Error (syntax error) has occurred in the vicinity of: select count(*) as count"; ERRORCODE: 100; NEXT: null
You are using count which is a keyword for your column custom name, the error you posted clearly says it: A Parser Error (syntax error)
This will do
select count(*) as quantity from dm_user;
and fetching result like
IDfCollection total = dql.execute(session, IDfQuery.DF_READ_QUERY);
while (total.next()){
cint = total.getInt("quantity");
will work
While #Miki answered it already but I like to add one small thing here that below code should work too if you haven't specified any alias.
{
IDfCollection total = dql.execute(session, IDfQuery.DF_READ_QUERY);
while (total.next()){
cint = total.getInt("count(*)");
}
}

UCanAccess data exception: numeric value out of range

I have a table called [Elenco_Aziende] from which I extract all the record in a resultset. [Elenco_Aziende] is in a relation one to many with other two tables called [Elenco_Autisti] and [Elenco_Veicoli] via a field called [Partita_IVA_Azienda] that is also primary key in [Elenco_Aziende] table.
After extracting all records from [Elenco_Aziende] I perform a loop for each value of [Partita_IVA_Azienda] and then open a new result set to try to read values in related fields of [Elenco_Autisti] and [Elenco_Veicoli] tables and do for each of them some operation.
And here comes strange thing: As long as [Partita_IVA_Azienda] (which is defined as a Text field in the Access DB) values are all the same length everything is OK when I try to read in [Elenco_Autisti] and [Elenco_Veicoli] tables, but if some of [Partita_IVA_Azienda] has a different length then I got error:
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.1 data exception: numeric value out of range
More precisely here is the nested loop scenario:
Connection con = DriverManager.getConnection("jdbc:ucanaccess://"
+ filepath);
String qry = "SELECT * FROM Elenco_Aziende";
ResultSet rs = stmt.executeQuery(qry);
String cognometest = "";
String nometest ="";
while (rs.next()) {
String partitaiva = "Partita IVA: "
+ rs.getString("Partita_IVA_Azienda") + "\n\r";
String partitaivazienda = rs.getString("Partita_IVA_Azienda");
Statement stmtautisti = con.createStatement();
System.out.println("Sto per eseguire la query per partita iva azienda = " + partitaivazienda + "\n\r");
String qryautisti = "SELECT * FROM Elenco_Autisti WHERE Partita_IVA_Azienda="
+ partitaivazienda; /*!!!!! AND HERE WHEN I EXECUTE NEXT QUERY IS WHERE I GET THE EXCEPTION net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.1 data exception: numeric value out of range more!!!!!*/
ResultSet rsautisti = stmtautisti.executeQuery(qryautisti);
while (rsautisti.next()) {
do something here
}
Statement stmtveicoli = con.createStatement();
String qryveicoli = "SELECT * FROM Elenco_Veicoli WHERE Partita_IVA_Azienda="
+ rs.getString("Partita_IVA_Azienda");
ResultSet rsveicoli = stmtveicoli.executeQuery(qryveicoli);
while (rsveicoli.next()) {
do something else here
}
that is as soon as I execute the query
String qryautisti = "SELECT * FROM Elenco_Autisti WHERE Partita_IVA_Azienda="+ partitaivazienda;
for a different length value of [Partita_IVA_Azienda] I get the problem.
I even tried to export the database in a comma separated value and reimporting it in a brand new one but it did not help. Furthermore, the problem seems to happen just for large number of records in tables [Elenco_Autisti] (138 records) and [Elenco_Veicoli] (287 records), while seems not to happen for small number of records. [Elenco_Aziende] is small (no more than 10 records).
According to the little of what I know about SQL, a WHERE with a text field should be written with the value in apostrophes:
String qryautisti = "SELECT * FROM Elenco_Autisti WHERE Partita_IVA_Azienda='"
+ partitaivazienda + "'";

Error: Before start of result set in Java

I know this would be a foolish question to ask but still i need to do this.
This is a basic program in java application where I want to use 3 queries simultaneously to print the table.
(I'm not using any Primary key in this case so please help me to resolve this without making my attributes as primary keys - I know this is not a good practice but for now i need to complete it.)
my code:
Connection con = null;
Statement stat1 = null, stat2 = null, stat3 = null;
ResultSet rs1, rs2, rs3;
stat1 = con.createStatement();
stat2 = con.createStatement();
stat3 = con.createStatement();
String str = "\nProduct\tC.P\tS.P.\tStock\tExpenditure\tSales";
info.setText(str);
String s1 = "SELECT type, cp, sp, stock FROM ts_items GROUP BY type ORDER BY type";
String s2 = "SELECT expenditure FROM ts_expenditure GROUP BY type ORDER BY type";
String s3 = "SELECT sales FROM ts_sales GROUP BY type ORDER BY type";
rs1 = stat1.executeQuery(s1);
rs2 = stat2.executeQuery(s2);
rs3 = stat3.executeQuery(s3);
String type;
int cp, sp, stock, expenditure, sales;
while( rs1.next() || rs2.next() || rs3.next() )
{
type = rs1.getString("type");
cp = rs1.getInt("cp");
sp = rs1.getInt("sp");
stock = rs1.getInt("stock");
expenditure = rs2.getInt("expenditure");
sales = rs3.getInt("sales");
info.append("\n" + type + "\t" + cp + "\t" + sp + "\t" + stock + "\t" + expenditure + "\t" + sales);
}
Output:
Runtime Exception: Before start of result set
This is the problem:
while( rs1.next() || rs2.next() || rs3.next() )
If rs1.next() returns true, rs2.next() and rs3.next() won't be called due to short-circuiting. So rs2 and rs3 will both be before the first row. And if rs1.next() returns false, then you couldn't read from that anyway...
I suspect you actually want:
while (rs1.next() && rs2.next() && rs3.next())
After all, you only want to keep going while all three result sets have more information, right?
It's not clear why you're not doing an appropriate join, to be honest. That would make a lot more sense to me... Then you wouldn't be trying to use multiple result sets on a single connection, and you wouldn't be relying on there being the exact same type values in all the different tables.
You do an OR so imagine only one ResultSet has a result.
What you end up with is trying to read from empty result sets.
Suppose rs1 has one result and rs3 has 3 results. Now as per your code it will fail for rs1.getString("type"); during second iteration.
Better to loop over each resultSet separately.
This is going to go badly wrong, in the event that there is a type value that's missing from one of your three tables. Your code just assumes you'll get all of the types from all of the tables. It may be the case for your current data set, but it means that your code is not at all robust.
I would seriously recommend having just one SQL statement, that has each of your three selects as subselects, then joins them all together. Your java can just iterate over the result from this one SQL statement.

I need a sql statement in java that finds an average with a where clause and returns value

So far my code is:
try{
stmt = con.createStatement();
String sql = "SELECT AVG(WPM) FROM Attempts WHERE Username = ('" + Login.loginUsername + "');
rs = stmt.executeQuery(sql);
int add1 = rs.getInt("AVG(WPM)");
System.out.println("avg temp is " + add1);
}
catch (SQLException err) {
System.out.println(err.getMessage());
}
my database is set up like so:
(PK) 'AttemptID' Integer AutoIncrement
'WPM' Integer
(FK) 'Username' Varchar(45)
I want it to return average WPM based on each username. If I change the line
int add1 = rs.getInt("AVG(WPM)");
to
String add1 = rs.getString("AVG(WPM)");
there is no difference. please help.
Try with double add1 = rs.getDouble(1);
Explanaition: rs.get...(1) gets the column based on the column index, not based on the name of the column. The database might change this when using functions in your select. Also, use double instead of int as AVG returns a double.
It looks like that you forget the statement rs.next()...
your sql have SQL injection ..
AVG function result maybe to float or double .
float f = rs.getFloat(1);//
I think you simply need to add a group by clause to your select statement. Your select statement would then read: select avg(WPD) from Attempts group by Usename where Username = ... That should correctly calculate the average WPD per user. Since you are using average I would think that the value returned is likely a double. In that case you should use rs.getDouble. Only a single value is selected in the query so you can use the index of the column to access it. The call will then be rs.getDouble(0). I hope you find this answer helpful.
Good luck,
Nikolai

Merging three queries that use 1:* relationships into one query

Lets say i have four tables i want to read from:
customer
customer_id, customer_name
1 Joe Bolggs
customer_orders
customer_id, order_no
----------------------------
1 1
1 2
1 3
customer_addresses
customer_id address
----------------------------
1 11 waterfall road
1 23 The broadway
customer_tel_no
customer_id number
----------------------------
1 523423423432
1 234342342343
The customer information shown above (for the customer with id=1) is to be stored in a Java object as shown below
public class Customer{
String customer_id;
String customerName;
ArrayList<String> customerOrders;
ArrayList<String> customerAddress;
ArrayList<String> customerTelephoneNumbers;
}
The only way i can think of to get the above information is by using three queries. The reason is that there is a 1:* relationship between the customer table and each of the other tables. To get the data i am doing something like this:
Customer customer = new Customer()
String customerSQL = "Select * from customer where customer_id = ?";
statement = getConnection().prepareStatement(contactsQuery);
statement.setString(1,1);
resultSet = statement.executeQuery();
while (resultSet.next()){
customer.customer_id = resultSet.get(1); //No getters/setters in this example
customer.customerName = resultSet.get(2);
}
String customerOrdersSQL = "Select * from customer_orders where customer_id = ?";
statement = getConnection().prepareStatement(customerOrdersSQL);
statement.setString(1,1);
resultSet = statement.executeQuery();
customer.customerOrders = new ArrayList();
while (resultSet.next()){
customer.customerOrders.add(resultSet.getString(2); // all the order numbers
}
String customerAddressesSQL = "Select * from customer_addresses where customer_id = ?";
statement = getConnection().prepareStatement(customerAddressesSQL );
statement.setString(1,1);
resultSet = statement.executeQuery();
customer.customerAddresses = new ArrayList();
while (resultSet.next()){
customer.customerAddresses.add(resultSet.getString(2); // all the addresses
}
String customerTelSQL = "Select * from customer_tel_no where customer_id = ?";
statement = getConnection().prepareStatement(customerTelSQL);
statement.setString(1,1);
resultSet = statement.executeQuery();
customer.customerTelephoneNumbers = new ArrayList();
while (resultSet.next()){
customer.customerTelephoneNumbers.add(resultSet.getString(2); // all the order numbers
}
The problem with the above is that i am making three calls to the database. Is there a way i can merge the above into a single query please?
I cant see how a join would work because for example, a join between customer and customer_orders will return a customer row for each row in customer_orders. Is there anyway i can merge the above three queries into one?
I would think that something like this would work:
SELECT c.customer_id, c.customer_name, o.order_no, a.address, t.number
FROM customer c LEFT JOIN customer_orders o ON c.customer_id = o.customer_id
LEFT JOIN customer_addresses a ON c.customer_id = a.customer_id
LEFT JOIN customer_tel_no t ON c.customer_id = t.customer_id
WHERE c.customer_id = ?
Then, in your code, after you execute the query:
while (resultSet.next())
{
customer.customerOrders.add(resultSet.getString(3));
customer.customerAddresses.add(resultSet.getString(4));
customer.customerTelephoneNumbers.add(resultSet.getString(5));
}
Of course, this does not take into account the fact that you will have null values along the way, so I'd advise checking for nulls to make sure that you aren't adding a lot of junk to your array lists. Still, that's probably a lot less costly than 3 separate queries.
Nothing prevents you from iterating and processing the joined result into your customer object. If your application is complex enough, you could look into ORM frameworks which would do that for you under the covers. If you are working with JavaEE, have a look at JPA.
use this query and reduce the number of call. And, in while loop process on data.
select customer.customer_id,customer.customer_name,order_no,address,number
from customer,customer_orders,customer_addresses,customer_tel_no
where customer.customer_id = customer_orders.customer_id
AND
customer.customer_id = customer_addresses.customer_id
AND
customer.customer_id = customer_tel_no.customer_id

Categories