Why Group by is working unexpectedly in JPQL eclipseLink? - eclipselink

Here is my query (jpql-eclipseLInk) -
"SELECT NEW com.nrbwlko.officeprojectmaven1.dao.ProjectProgressDao(c.projectMemberFk.projectMember,"
+ "COUNT(c),"
+ "CASE (c.materialDetailFk.materialType.materialType) WHEN 'plate' "
+ "THEN SUM(c.componentLength*c.componentWidth*c.materialDetailFk.unitWeight*c.projectMemberFk.memberQty*c.projectMemberFk.projectUnitIdFk.unitQty)/1000000 "
+ "ELSE SUM(c.componentLength*c.materialDetailFk.unitWeight*c.projectMemberFk.memberQty*c.projectMemberFk.projectUnitIdFk.unitQty)/1000 END, "
+ "CASE (c.materialDetailFk.materialType.materialType) WHEN 'plate' "
+ "THEN SUM(c.componentLength*c.componentWidth*c.materialDetailFk.unitWeight*c.projectMemberFk.memberQty)/1000000 "
+ "ELSE SUM(c.componentLength*c.materialDetailFk.unitWeight*c.projectMemberFk.memberQty)/1000 END, "
+ "CASE (c.materialDetailFk.materialType.materialType) WHEN 'plate' "
+ "THEN SUM(c.componentLength*c.componentWidth*c.materialDetailFk.unitWeight*c.projectMemberFk.fabricatedQty)/1000000 "
+ "ELSE SUM(c.componentLength*c.materialDetailFk.unitWeight*c.projectMemberFk.fabricatedQty)/1000 END, "
+ "CASE (c.materialDetailFk.materialType.materialType) WHEN 'plate' "
+ "THEN SUM(c.componentLength*c.componentWidth*c.materialDetailFk.unitWeight)/1000000 "
+ "ELSE SUM(c.componentLength*c.materialDetailFk.unitWeight)/1000 END) "
+ "FROM CuttingList c "
+ "WHERE c.projectMemberFk.projectUnitIdFk.projectId.projectId = :id "
+ "GROUP BY c.projectMemberFk.projectMember"
First Sum is the Total sum (consisting of groups by members obviously) --- which is not equal to the sum of individual row . When i group by individual row id (c.id) Total is 28193 (which is correct value i checked it manual calculation) But when i group it by member value is 28103.
I tried various combination and unless each row is individual total value is always less than actual value. It's part of my android app backend, all work is done except this data mismatch which makes my last 6 month work useless. I desperately need help.
One more information i would like to share that if i group it by Material (query provided below) then Total value is again correct, for example
Here is another query from same table Giving correct Total Material Weight but this time it grouped by material and not by member
"SELECT NEW com.nrbwlko.officeprojectmaven1.dao.MaterialSummeryByProjectDao(c.materialDetailFk.materialName,COUNT(c),"
+ "CASE (c.materialDetailFk.materialType.materialType) WHEN 'plate' "
+ "THEN SUM(c.componentLength*c.componentWidth*c.materialDetailFk.unitWeight*c.projectMemberFk.memberQty*c.projectMemberFk.projectUnitIdFk.unitQty)/1000000 "
+ "ELSE SUM(c.componentLength*c.materialDetailFk.unitWeight*c.projectMemberFk.memberQty*c.projectMemberFk.projectUnitIdFk.unitQty)/1000 END) "
+ "FROM CuttingList c "
+ "WHERE c.projectMemberFk.projectUnitIdFk.projectId.projectId = :id "
+ "GROUP BY c.materialDetailFk.materialName"
giving me material grouped in 4 type and total is 28193 (correct value)
(Count(c) in both case is correct which is 6 nos)
here is the result when i grouped by material -- (Total is correct)
I can provide more information if required.

Related

SQL Union not working when one table is empty

Hi I am trying to read data from different tables with a SELECT statement and want to use UNION to get one dataset in the end. It is possible that one table does not (yet) contain data. In this case I can read the data from the first two successfully but once I use UNION to combine it with the data from the empty table the resulting dataset will be empty as well, even though it contained data from the first two datasets before.
My problem is, data is shifted between these tables irregularily so there is no way for me to know in which of the three tables I will find the data and in any case usually I have to combine results from more than one table to get the entire dataset I need (one contains data only 3 months back, the other two contain data for the last and the current year - depending on the period I need the data for it is possible that I have to look in all the three of them to collect all the data I need).
Do you know how I can check out all three tables and read data to collect the entire dataset I need?
I also tested if everything works in case all the three tables contain data, et voila it worked and I retrieved all the data I needed. So the statement itself should be OK, just not applicable to the special case where one table does not contain data.
I am using Python to connect to the database and retrieve the data via an sql statement.
So my sql statement currently looks like this:
sql_stmt = (
"select " + sql_param+" from " + db_table +
" where datum>=" + season_start_sql + " and datum<" + season_end_sql +
" and statnr="+str(statnr) +
" union" +
" select " + sql_param+" from " + db_table +
" where datum=" + season_end_sql + " and stdmin<=" + season_end_time_sql +
" and statnr="+str(statnr) +
" union" +
" select " + sql_param + " from " + db_table + "_" + str(season_start.year) +
" where datum>=" + season_start_sql + " and datum<" + season_end_sql +
" and statnr=" + str(statnr) +
" union" +
" select " + sql_param + " from " + db_table + "_" + str(season_start.year) +
" where datum=" + season_end_sql + " and stdmin<=" + season_end_time_sql +
" and statnr=" + str(statnr) +
" union" +
" select " + sql_param + " from " + db_table + "_" + str(next_year) +
" where datum>=" + season_start_sql + " and datum<" + season_end_sql +
" and statnr=" + str(statnr) +
" union" +
" select " + sql_param + " from " + db_table + "_" + str(next_year) +
" where datum=" + season_end_sql + " and stdmin<=" + season_end_time_sql +
" and statnr=" + str(statnr) +
" order by datumsec")
This statement is simply untrue:
once I use UNION to combine it with the data from the empty table the resulting dataset will be empty as well, even though it contained data from the first two datasets before.
If one of the components of a UNION is empty, then you will still get the results from the other tables.
Note: If one of the tables does not exist -- which is quite different from being empty -- then the query returns an error, but not an empty result.
I will note that in general you should be using UNION ALL instead of UNION, to avoid the overhead of removing duplicate values. And your code is wide open to SQL injection attacks and to unexpected syntax errors. I would question whether your application can be designed so you don't have to use dynamic SQL for this purpose.

Multiple conditions in SELECT Statement

I am checking my database to see if there are any overlapping appointments. It works for ADDing appointments, but when I go to UPDATE my SQL counts the record I am updating as an overlapping appointment when I try to change it. Here is the SQL I am using in the UPDATE statement.
"SELECT * FROM appointments " +
"WHERE ('" + start + "' BETWEEN Start and End OR '" + end + "'
BETWEEN Start AND End OR '" + start + "' > Start AND '" + end + "' < End AND
Appointment_ID <> " + id + ")";
This still pulls the record with the appointment id that I'm giving it. Anyone have any suggestions on how to exclude any appointments that have the id I'm updating but still meeting the other criteria.
currently, you are only checking for the id of the appointment to update when the third clause you have chained with ORs triggers because of the order of operations for OR and AND. Your query fetches a result when the start date is overlapping with the appointment OR your end date is is overlapping with the appointment OR it has a different ID and the dates are encapsulating the appointment.
Also, you shouldn't need to have brackets around your whole WHERE clause but you can use the opening bracket and move the closing bracket to make sure that the condition with the id is always evaluated like so:
"SELECT * FROM appointments " +
"WHERE ('" + start + "' BETWEEN Start and End OR '" + end + "'
BETWEEN Start AND End OR '" + start + "' > Start AND '" + end + "' < End) AND
Appointment_ID <> " + id;

Does OpenJPA support Where In Select queries?

So I have a query as follows that I am trying to run on DB2 using OpenJPA:
#NamedQuery(name="getStuff",
query = "SELECT mtl.final, mtl.entity " +
"FROM MCT mct, MTL mtl " +
"WHERE ~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " +
"AND mct.cTotPK.Label IN ( SELECT mccp.cCPPK.cPLC " +
"FROM MCCP mccp WHERE mccp.cCPPK.cLC = '#My String#')")
I can get rid of the WHERE IN SELECT statements (bottom two lines) and it will run. So I can't figure out what's wrong with the bottom two lines.
Whenever I run this though I get the DB2 error:
DB2 SQL Error: SQLCODE=-199, SQLSTATE=42601, SQLERRMC=FOR;AND OR HAVING GROUP INTERSECT ORDER ) FETCH EXCEPT MINUS UNION, DRIVER=3.61.75
When I looked this error up I found that it is an "illegal use of a keyword" but I really don't know what else I could do. Is there an alternative to the WHERE IN SELECT that I could try out? Thanks for the help.

My C# SQL Select statement is not picking up any records in my table

I have 4 records in my SQL table that and I'm doing a SQL select statement to select records based on a certain criteria but I'm not picking any records up. Can someone please help?
Here is my SELECT statement:
string Sql = "";
Sql = #"SELECT * FROM " + _dtlName + "
WHERE Shipper_No = '" + sidNo + "'
AND Job_Code != '" + "R" + "'";
I have 3 records that have a Null for Job_Code and 1 record that has an R.
Based on that, I should pickup the 3 records with the NULL Job_Code but it returns 0 records.
I suspect the problem is that a comparison between any non-null value and a null value doesn't return a value of true or false, but null. So your query should probably be:
string sql = "SELECT * FROM " + _dtlName + " WHERE Shipper_No = #ShipperNo " +
"AND (Job_Code IS NULL OR Job_Code != 'R')";
(Note that I've extracted a parameter for Shipper_No - you shouldn't be including values directly in your SQL like that. Obviously you'll need to then set the parameter value in the SQL command.)
Also note that <> is more common in SQL to represent "not equal to", but I believe T-SQL allows either form.
Try,
Sql = #"SELECT * FROM " + _dtlName + " WHERE Shipper_No = '" + sidNo + "' AND Job_Code NOT IN ('R')";
I think your query should be more like this since you want to select the NULL values.
string Sql = String.Format("SELECT * " +
"FROM {0} " +
"WHERE Shipper_No = {1} AND " +
" Job_Code IS NULL",
_dtlName, sidNo)

Sorting null-data last in database query

i have an application where i order make a query to my database with an ORDER BY clause, it will order them in alphabetical order. i only have one small problem, it happens fairly often that one of the strings that the query is ordering by contains nothing (string="") when sorting in alphabetical order these get populated at the top of the list infront om a,b,c... i plain and simple dont want this. after a lot of googling i found on an oracle forum that i should change the SORT BY part of the query to "SORT BY xxx ASC NULLS LAST" this caused a fatal error when querying.
how shall i go by fixing this seemingly small issue?
here is my query statement as is today.
public Cursor fetchAllDatesByTag() {
return mdiktationsDb.rawQuery("SELECT " + KEY_DATEID + "," +" " + KEY_DATE + "," + " " + KEY_TIME + "," + " " + KEY_DICTTAG + "," + " " + KEY_DICTLISTIMAGE + " FROM " + DATABASE_TABLE + " ORDER BY " + KEY_DICTTAG + " ASC", null);
}
use a CASE equivalent in your ORDER BY
Like
ORDER BY CASE column WHEN NULL THEN 1 ELSE 0 END, column
so then it orders by the nulls first, then the actual column.
EDIT: And if you want to filter ""s (blank strings) or whatever else, you can employ this same method... assigning a numeric value to it and sorting before the alphabetizing.
EDIT2:
....+ " ORDER BY CASE " + KEY_DICTTAG + "WHEN NULL THEN 1 ELSE 0 END, " + KEY_DICTTAG + " ASC"
Solution one:
ORDER BY foo NULLS LAST
and
ORDER BY foo NULLS FIRST
But this seems to work only with numeric columns :(
Solution two:
ORDER BY IF(ISNULL(my_field),1,0),my_field
which will create a "fake"-column that just consist 0 or 1, depending on if my_field is null or not null, and sort on that. the fields that are not null will come first. in a second step, SQL will sort my_field, like before.
How about adding a WHERE field IS NOT NULL. This way you shouldn't get any null values back from your query.