SQL returning the count from wrong table - sql

This SQL is returning the record count of table Dims instead returning the record count of table BIDdetails. How can I fix?
BIDReportSearch.CommandText = ("SELECT BIDdetails.Origin, BIDdetails.Destination,
Round(Sum(Dims.ChargeableWeight)) as CWeight, count(BIDdetails.Origin) as NoOfShpt
FROM BIDdetails LEFT JOIN DIMS ON BidDetails.BID=Dims.BID
where BIDdetails.OrgCountry<>'AE' and BIDdetails.DestCountry='AE' and
BIDdetails.ClosingDate>=#" & dtpBIDfrom.Value & "# and BIDdetails.ClosingDate<=#" &
dtpBIDto.Value & "# GROUP BY BIDdetails.Origin, BIDdetails.Destination
ORDER BY Round(Sum(Dims.ChargeableWeight)) DESC")

The expression:
count(BIDdetails.Origin)
simply counts the number of non-NULL values of BIDdetails.Origin in each group. Because you are actually grouping by the field, that would be the number of rows in each group.
You can get what you want in most databases by using count(distinct) on a unique identifier. Alas, MS Access doesn't support count(distinct) so such a query is much harder to write in Access. You can get just the count field by doing:
SELECT BIDdetails.Origin, BIDdetails.Destination, count(*) as NoOfShpt
FROM BIDdetails
where BIDdetails.OrgCountry <> 'AE' and BIDdetails.DestCountry='AE' and
BIDdetails.ClosingDate>=#" & dtpBIDfrom.Value & "# and BIDdetails.ClosingDate<=#" & dtpBIDto.Value & "#
GROUP BY BIDdetails.Origin, BIDdetails.Destination;
And then combining the results either in your application or by joining this query back into the original one.
EDIT:
This is your original query:
SELECT d.Origin, d.Destination,
Round(Sum(Dims.ChargeableWeight)) as CWeight, count(d.Origin) as NoOfShpt
FROM BIDdetails as d LEFT JOIN
DIMS
ON BidDetails.BID=Dims.BID
where d.OrgCountry <> 'AE' and d.DestCountry='AE' and
d.ClosingDate> = #" & d.Value & "# and d.ClosingDate<=#" & dtpBIDto.Value & "#
GROUP BY d.Origin, d.Destination
ORDER BY Round(Sum(Dims.ChargeableWeight)) DESC
There is another approach, where you aggregate first by the details and then again. I think that is easier in this case:
SELECT Origin, Destination, SUM(CWeight) as CWeight, COUNT(*) as NumShip
FROM (SELECT d.id, d.Origin, d.Destination,
Round(Sum(Dims.ChargeableWeight)) as CWeight, count(d.Origin) as NoOfShpt
FROM BIDdetails as d LEFT JOIN
DIMS
ON BidDetails.BID = Dims.BID
where d.OrgCountry <> 'AE' and d.DestCountry='AE' and
d.ClosingDate> = #" & d.Value & "# and d.ClosingDate<=#" & dtpBIDto.Value & "#
GROUP BY d.id, d.Origin, d.Destination
) as d
GROUP BY Origin, Destination
ORDER BY Round(Sum(CWeight)) DESC;
d.id refers to whatever the unique id is for what you want to count.

Related

SQL VBA Group by error with TRUNC() function

im doing a query on vba excel, i ave a problem with this query:
SQLStr = "SELECT DISTINCT (t2.COD_CF) AS CODICE_CLIENTE, (t2.RAG_SOC_CF) AS CLIENTE, (t1.DES_HEAD_DOC) AS COMMESSA_E_DESCRIZIONE, t1.DATA_PREV_FIN_LAV AS GREZZO_CONFERMATO, MIN(t4.DATA_INIZIO) AS PRIMO_CARICO, MAX(t4.DATA_FINE) AS ULTIMO_CARICO, " & _
"(TRUNC(MAX(t1.DATA_PREV_FIN_LAV)) - TRUNC(t4.DATA_INIZIO) ) - " & _
"((((TRUNC(MAX(t1.DATA_PREV_FIN_LAV),'D'))-(TRUNC(t4.DATA_INIZIO,'D')))/7)*2) - " & _
"(CASE WHEN TO_CHAR(t4.DATA_INIZIO,'DY','nls_date_language=english')='SUN' THEN 1 ELSE 0 END) - " & _
"(CASE WHEN TO_CHAR(MAX(t1.DATA_PREV_FIN_LAV),'DY','nls_date_language=english')='SAT' THEN 1 ELSE 0 END) as GG_DIFFERENZA " & _
"FROM COMM_LAV t1 " & _
"INNER JOIN CF t2 ON t1.COD_CF_INTE = t2.COD_CF " & _
"INNER JOIN COMM_LAV_LNK t3 ON t1.DOC_ID = t3.DOC_ID " & _
"INNER JOIN ORP_EFF_CICLI_ESEC t4 ON t3.LNK_DOC_ID = t4.DOC_ID " & _
"WHERE t1.DATA_PREV_FIN_LAV >= '" & startDate & "' AND t1.DATA_PREV_FIN_LAV <= '" & endDate & "' AND t4.COD_CICLO <> 'LEV01' " & _
"GROUP BY t2.COD_CF, t2.RAG_SOC_CF, t1.DES_HEAD_DOC, t1.DATA_PREV_FIN_LAV " & _
"ORDER BY t1.DES_HEAD_DOC, t1.DATA_PREV_FIN_LAV, MIN(t4.DATA_INIZIO) "
I get this error: ORA-00979: not a GROUP BY expression
this error there is only when i do the TRUNC() function, someone can help me and explain this group by
UPDATE
I tryed to use oracle and i hav e edit the query like this:
SELECT (t2.COD_CF) AS CODICE_CLIENTE, (t2.RAG_SOC_CF) AS CLIENTE, (t1.DES_HEAD_DOC) AS COMMESSA_E_DESCRIZIONE, t1.DATA_PREV_FIN_LAV AS GREZZO_CONFERMATO, MIN(t4.DATA_INIZIO) AS PRIMO_CARICO, MAX(t4.DATA_FINE) AS ULTIMO_CARICO,
(TRUNC(MAX(t1.DATA_PREV_FIN_LAV)) - TRUNC(t4.DATA_INIZIO)) AS DIFF
FROM COMM_LAV t1
INNER JOIN CF t2 ON t1.COD_CF_INTE = t2.COD_CF
INNER JOIN COMM_LAV_LNK t3 ON t1.DOC_ID = t3.DOC_ID
INNER JOIN ORP_EFF_CICLI_ESEC t4 ON t3.LNK_DOC_ID = t4.DOC_ID
WHERE t1.DATA_PREV_FIN_LAV >= '01-OCT-20' AND t1.DATA_PREV_FIN_LAV <= '30-OCT-20' AND t4.COD_CICLO <> 'LEV01'
GROUP BY t2.COD_CF, t2.RAG_SOC_CF, t1.DES_HEAD_DOC, t1.DATA_PREV_FIN_LAV
ORDER BY t1.DES_HEAD_DOC, t1.DATA_PREV_FIN_LAV, MIN(t4.DATA_INIZIO)
but i have always this error: ORA-00979: not a GROUP BY expression
Why the trunc function give me this error?
The GROUP BY clause needs to include all the fields in your SELECT that are not being GROUPED. You have omitted this one:
(TRUNC(MAX(t1.DATA_PREV_FIN_LAV)) - TRUNC(t4.DATA_INIZIO)) AS DIFF
Even though you have an aggregation function in there (MAX), overall this is a TRUNC statement and so is not an aggregation.
I think logically the following 2 statements are the same (at least as long as B < A):
MAX(A) - B == MAX(A-B)
therefore you should be able to re-write your statement as the following and still get the same result:
MAX(TRUNC(t1.DATA_PREV_FIN_LAV) - TRUNC(t4.DATA_INIZIO)) AS DIFF
You are missing the column TRUNC(t4.DATA_INIZIO) in the GROUP BY:
SELECT t2.COD_CF AS CODICE_CLIENTE, t2.RAG_SOC_CF AS CLIENTE,
t1.DES_HEAD_DOC AS COMMESSA_E_DESCRIZIONE,
t1.DATA_PREV_FIN_LAV AS GREZZO_CONFERMATO,
MIN(t4.DATA_INIZIO) AS PRIMO_CARICO,
MAX(t4.DATA_FINE) AS ULTIMO_CARICO,
(TRUNC(MAX(t1.DATA_PREV_FIN_LAV)) -
TRUNC(t4.DATA_INIZIO)
--------^ Not in GROUP BY
) AS DIFF
FROM COMM_LAV t1 JOIN
CF t2
ON t1.COD_CF_INTE = t2.COD_CF JOIN
COMM_LAV_LNK t3
ON t1.DOC_ID = t3.DOC_ID JOIN
ORP_EFF_CICLI_ESEC t4
ON t3.LNK_DOC_ID = t4.DOC_ID JOIN
WHERE t1.DATA_PREV_FIN_LAV >= DATE '2020-10-01' AND
t1.DATA_PREV_FIN_LAV <= DATE '2020-10-30' AND
t4.COD_CICLO <> 'LEV01'
GROUP BY t2.COD_CF, t2.RAG_SOC_CF, t1.DES_HEAD_DOC, t1.DATA_PREV_FIN_LAV,
TRUNC(t4.DATA_INIZIO)
---------^ add to GROUP BY
ORDER BY t1.DES_HEAD_DOC, t1.DATA_PREV_FIN_LAV, MIN(t4.DATA_INIZIO);
Note that Oracle supports date literals using the DATE keyword. I strongly recommend that you use that.

Add a total of summaries at the top of SQL (Access)

I have a table of foods (FOODS) and a table of food groups (FOOD_GROUP). I have build a list to summarize available food count for each group based on the search term entered by the user:
SELECT FOOD_GROUP.FoodGroupID, FOOD_GROUP.FoodGroupName, Count(FOODS.FoodID) AS CntOfFoodID
FROM FOOD_GROUP LEFT JOIN FOODS ON FOOD_GROUP.FoodGroupID = FOODS.FoodGroupID
WHERE (((FOODS.FoodName) Like ("*" & [Forms]![FoodSearch]![search_term] & "*")))
GROUP BY FOOD_GROUP.FoodGroupID, FOOD_GROUP.FoodGroupName
ORDER BY FOOD_GROUP.FoodGroupName;
But now it gets tricky. I want to add a summary row at the top that list. Here is a nearly simmilar example:
I guess I must do something like:
SELECT '0000', 'Show all foods', Count(FOODS.FoodID) AS CntOfFoodID
FROM FOODS
WHERE (((FOODS.FoodName) Like ("*" & [Forms]![FoodSearch]![search_term] & "*")))
UNION
SELECT FOOD_GROUP.FoodGroupID, FOOD_GROUP.FoodGroupName, Count(FOODS.FoodID) AS CntOfFoodID
FROM FOOD_GROUP LEFT JOIN FOODS ON FOOD_GROUP.FoodGroupID = FOODS.FoodGroupID
WHERE (((FOODS.FoodName) Like ("*" & [Forms]![FoodSearch]![search_term] & "*")))
GROUP BY FOOD_GROUP.FoodGroupID, FOOD_GROUP.FoodGroupName
ORDER BY FOOD_GROUP.FoodGroupName;
But GROUP BY fails and if I take out GROUP BY than FoodGroupID is missing.
Any hints?
I think this should work:
SELECT '0000', 'Show all foods', Count(f.FoodID) AS CntOfFoodID
FROM FOODS as f
WHERE f.FoodName Like "*" & [Forms]![FoodSearch]![search_term] & "*"
UNION ALL
SELECT fg.FoodGroupID, fg.FoodGroupName, Count(f.FoodID) AS CntOfFoodID
FROM FOOD_GROUP fg LEFT JOIN
FOODS as f
ON fg.FoodGroupID = f.FoodGroupID
WHERE f.FoodName Like "*" & [Forms]![FoodSearch]![search_term] & "*"
GROUP BY fg.FoodGroupID, fg.FoodGroupName
ORDER BY 1;
The changes are:
Use UNION instead of UNION ALL. This is more efficient.
The ORDER BY does not refer to a column name (especially one only in the second subquery).
The use of table aliases just simplifies the query; it doesn't affect the logic or performance.

Sql Joins on multiple table returning product of two columns

I am trying to generate a report on a sql server database in asp.net and I am getting the results of some columns as a product of two columns. Here is the code
comm.CommandText = "SELECT Count(Courses.CourseID) AS CourseCount, Count(Students.StudentID) AS StudentCount, Schools.Name, Schools.StartDate, Schools.SchoolFees " +
"FROM Schools" +
"LEFT JOIN Courses ON (Schools.SchoolID = Courses.SchoolID)" +
"LEFT JOIN Students ON (Schools.SchoolID = Students.SchoolID) " +
"WHERE Schools.Active = 1 " +
"GROUP BY Schools.Name, Schools.StartDate, Schools.SchoolFees";
When I run the code, the result displays, but the columns for "CourseCount" and "StudentCount" display a value that is a product of each individual column. "CourseCount" is normally 288 and "StudentCount" is 38 but when I run the code, both "CourseCount" and "StudentCount" display 10944 which is 38 x 288.
Anyway I can make them display the correct values?
Changing your code from using a count of all rows, to a count of distinct values only, should return the results you expect
comm.CommandText = "SELECT Count(DISTINCT Courses.CourseID) AS CourseCount, Count(DISTINCT Students.StudentID) AS StudentCount, Schools.Name, Schools.StartDate, Schools.SchoolFees " +
"FROM Schools" +
"LEFT JOIN Courses ON (Schools.SchoolID = Courses.SchoolID)" +
"LEFT JOIN Students ON (Schools.SchoolID = Students.SchoolID) " +
"WHERE Schools.Active = 1 " +
"GROUP BY Schools.Name, Schools.StartDate, Schools.SchoolFees";
The results being returned are technically correct, if all schools have courses, and all courses have students
As stated above, it is how you are using the COUNT (), You are asking it to count all, which is why it returns so many. Use count on just the two values you want counted.
This might perform better than the DISTINCT Count method..
comm.CommandText =
"SELECT cc.CourseCount, sc.StudentCount, Schools.Name, Schools.StartDate, Schools.SchoolFees " +
"FROM Schools" +
"OUTER APPLY (SELECT Count(Students.StudentID) StudentCount FROM Students WHERE Students.SchoolID = Schools.SchoolID) sc " +
"OUTER APPLY (SELECT Count(Courses.CourseID) CourseCount FROM Courses WHERE Courses.SchoolID = Schools.SchoolID) cc " +
"WHERE Schools.Active = 1 ";

Access Select Query to show the same field with a different criteria

I have a select query in Access 2010 which shows a 'Level Name' where the 'Period ID' is set to 1
How can i add another field to the query which also shows the Level Name where the Period ID is set to 2?
I would like them both to be next to each other in separate rows
For reference, my current query looks like:
SELECT
qryMaster.[First Name] & " " & qryMaster.[Last Name] AS ChildName,
qryMaster.LevelName
FROM
qryMaster
WHERE
(
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 1)
);
I have added a picture of how my current query looks like in a sub form. I would like a new Column next to september, but for a different period
A WHERE clause is always for all fields. So if you want two different WHERE clauses then you need two queries.
Otherwise try
AND (qryMaster.PeriodID In(1,2))
I know this thread was active five month ago, but I had the same problem, found this page with google. Asuming others will arrive here too, I'll post the two solutions that I found below.
SELECT t1.ChildName, t1.LevelName1, qryMaster.LevelName
FROM
((SELECT
qryMaster.[First Name] & " " & qryMaster.[Last Name] AS ChildName,
qryMaster.LevelName as LevelName1
FROM qryMaster
WHERE
(
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 1)
)) AS t1)
LEFT JOIN qryMaster
ON t1.ChildName = (qryMaster.[First Name] & " " & qryMaster.[Last Name])
WHERE (
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 2)
)
As I do not have your data I couldn't test the code for your data, therefore I am not sure whether the "ON" clause works like this. In my case I have some customer ID there.
And the second one:
SELECT t1.[First Name] & " " & t1.[Last Name] AS ChildName, t1.LevelName AS LevelName1, t2.levelName AS LevelName2
FROM qryMaster t1
INNER JOIN qryMaster t2 ON t1.Childname=(t2.[First Name] & " " & t2.[Last Name])
WHERE (
(t1.ClassID = [Forms]![frmViewRecords_subject]![cboClass]) AND
(t1.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject]) AND
(t1.PeriodID = 1) AND
(t2.ClassID = [Forms]![frmViewRecords_subject]![cboClass]) AND
(t2.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject]) AND
(t2.PeriodID = 2)
)

Multiple select statements in access vba

I am trying to insert 2 count numbers into a table as one record in access through vba and for some reason it is saying the number of query values and destination fields are not the same when I try to run it. I am very confused why this is happening. Any help would be greatly appreciated
TotalVerified = " INSERT INTO Totals([TOTAL VERIFIED FORMULARIES], [TOTAL AVAILABLE FOR IMPORT]) " & _
"SELECT COUNT([FORMULARY ID]) " & _
"FROM VerifiedFormularies " & _
"AND COUNT([FORMULARY ID])" & _
"FROM ImportMetricsIDs"
I think the query you want is:
INSERT INTO Totals([TOTAL VERIFIED FORMULARIES], [TOTAL AVAILABLE FOR IMPORT])
SELECT CNT1, CNT2
FROM (SELECT COUNT([FORMULARY ID]) as CNT1 FROM VerifiedFormularies) as c1 CROSS JOIN
(SELECT COUNT([FORMULARY ID]) as CNT2 FROMImportMetricsIDs) as c2;
AND is a boolean operator, typically used in a WHERE clause, ON clause, or in an iif() expression. It doesn't connect the values from two subqueries.