SQL VBA Group by error with TRUNC() function - sql

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.

Related

sql update function with a left join

I am having some trouble writing a sql update function. I Have a table of quotes and a second table of products associated with those quotes. I am trying to set all the statuses of quotes with certain $ values based on the products. I cant seem to format this query correctly (code below). I know code is limited to 1 ID currently trying to test with 1 before I remove that portion.
sqlStringUpdate = "UPDATE fq SET fq.spQuoteStatus = 5 From factQuote fq (LEFT JOIN FactQuoteProduct as fqp on fq.spQuoteID=fqp.fk_spQuoteID) " & _
"WHERE fq.spQuoteID = 4844 and ((sum(fqp.ItemTotal) <2000 and fq.quoteDate < #" & firstset & "#) or ( fq.bu=3401 and sum(fqp.ItemTotal) <10000 and fq.quoteDate < #" & secondset & "# ) or ( fq.bu>3401 and sum(fqp.ItemTotal) <10000 and fq.quoteDate < #" & secondset & "#));"
error code: error 3075(syntax error (missing operator) in query expression '5 Left JOIN factQUotePRoduct as fqp on fq.spQUoteID=fqp.fk_spQuoteID')
first problem is the LEFT JOIN should not be in parenthesis.
second problem, you need to calculate the aggregate before the update, you can solve this using CTE syntax, try something like this:
;with
fqp as (
select fk_spQuoteID, sum(ItemTotal) sum_ItemTotal
from FactQuoteProduct
group by fk_spQuoteID
)
UPDATE fq SET fq.spQuoteStatus = 5
From factQuote fq
LEFT JOIN fqp on fq.spQuoteID=fqp.fk_spQuoteID
WHERE fq.spQuoteID = 4844
and (
(fqp.sum_ItemTotal <2000 and fq.quoteDate < #firstset)
or ( fq.bu=3401 and fqp.sum_ItemTotal <10000 and fq.quoteDate < #secondset )
or ( fq.bu>3401 and fqp.sum_ItemTotal <10000 and fq.quoteDate < #secondset )
);
if you are not common with CTE syntax you can use nested select like this:
UPDATE fq SET fq.spQuoteStatus = 5
From factQuote fq
LEFT JOIN (
select fk_spQuoteID, sum(ItemTotal) sum_ItemTotal
from FactQuoteProduct
group by fk_spQuoteID
) as fqp on fq.spQuoteID=fqp.fk_spQuoteID
WHERE fq.spQuoteID = 4844
and (
(fqp.sum_ItemTotal <2000 and fq.quoteDate < #firstset)
or ( fq.bu=3401 and fqp.sum_ItemTotal <10000 and fq.quoteDate < #secondset )
or ( fq.bu>3401 and fqp.sum_ItemTotal <10000 and fq.quoteDate < #secondset )
);
this should do the trick

Insert Into SQL VBA

I am trying to select records that are in the first table but not in the second table and insert them into the second table using a sql statement in VBA. I have started it below but I am not sure why it won't work. I am rather new to sql so any help would be greatly appreciated.
MySQL = "INSERT INTO Clients ()" & _
"SELECT DISTINCT DD.[Client ID] " & _
"FROM " & tableName & " as DD " & _
"Where DD.[Client ID] NOT IN (SELECT DD.[Client ID] FROM " & tableName & " as DD)"
First, you need supply field list to insert statement:
INSERT INTO Clients (ClientID)...
Second, your query doesn't insert any rows, because you check ClientID presence in same table. Did you mean someting like next:
"Where DD.[Client ID] NOT IN (SELECT DD2.[Client ID] FROM " & tableName2 & " as DD2)"

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.

Insert Into SQL Statement error 3346

I am trying to INSERT INTO a table in SQL but for some reason it says the number of query values and destination fields are not the same and I'm not sure why it is saying that. I have researched the error (3346) with no luck for a fix. I am rather new to VBA so any help would be greatly appreciated.
"INSERT INTO Clients (Col1, Col2, Col3)" & _
"SELECT DISTINCT DD.[Client ID] " & _
"FROM " & tableName & " as DD " & _
"Where CL.[Client ID] NOT IN (SELECT DD.[Client ID] FROM " & tableName & " as DD)"
You are trying to insert into 3 columns from one column it's confused
this will work:
"INSERT INTO Clients (Col1)" & _
"SELECT DISTINCT DD.[Client ID] " & _
"FROM " & tableName & " as DD " & _
"Where DD.[Client ID] NOT IN (SELECT DD.[Client ID] FROM " & tableName & " as DD)"
but it does not insert any row because there is no result for select statement.
Think a little more on it and decide exactly what do you want to insert into where?

SQL returning the count from wrong table

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.