Error with group by statement? - sql

I'm getting the following error when I run this code. please help me out.
SELECT store, COUNT(DISTINCT saledate), CountNov, CountDec, SumNov, SumDec, (SumNov/CountNov) AS NovAvgRvn, (SumDec/CountDec) AS DecAvgRvn FROM
(
SELECT store, saledate,
CASE WHEN SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN amt END) IS NULL THEN 0
ELSE SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN amt END)
END AS SumNov,
CASE WHEN SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN amt END) IS NULL THEN 0
ELSE SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN amt END)
END AS SumDec,
CASE WHEN COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN saledate END) IS NULL THEN 0
ELSE COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN saledate END)
END AS CountNov,
CASE WHEN COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN saledate END) IS NULL THEN 0
ELSE COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN saledate END)
END AS CountDec
FROM trnsact
WHERE stype = 'p'
GROUP BY store, saledate
) AS T1
WHERE CountDec > 0 AND CountNov > 0
GROUP BY store
ORDER BY store;
Error:
Error Code - 3504
Error Message - [Teradata Database] [TeraJDBC 15.10.00.05] [Error 3504] [SQLState HY000] Selected non-aggregate values must be part of the associated group.

Why are you using a nested query for this?
SELECT store, COUNT(DISTINCT saledate),
SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 11 THEN amt ELSE 0 END) as SumNov,
SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 11 THEN amt ELSE 0 END) as SumDec,
COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN 11 THEN saledate END) as CountNov,
COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN 12 THEN saledate END) as CountDec
FROM trnsact
WHERE stype = 'p'
GROUP BY store;
Notes:
COUNT() never returns NULL so there is no need for the CASE at all.
With an ELSE clause, the SUM() doesn't return NULL either (there would have to be no rows matching for the SUM() to return NULL, and with no matching rows in the group, the group wouldn't exist).
EXTRACT() returns a number, so compare to a number.

Anything that is in your select statement which is not an aggregate like SUM, AVG etc. need to be included in your group by clause if you have a group by clause
Try this hope it helps:
SELECT store, COUNT(DISTINCT saledate), CountNov, CountDec, SumNov, SumDec, (SumNov/CountNov) AS NovAvgRvn, (SumDec/CountDec) AS DecAvgRvn FROM
(
SELECT store, saledate,
CASE WHEN
SUM(CASE EXTRACT(MONTH FROM saledate)
WHEN '11' THEN amt END) IS NULL THEN 0
ELSE SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN amt END)
END AS SumNov,
CASE WHEN SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN amt END) IS NULL THEN 0
ELSE SUM(CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN amt END)
END AS SumDec,
CASE WHEN COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN saledate END) IS NULL THEN 0
ELSE COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '11' THEN saledate END)
END AS CountNov,
CASE WHEN COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN saledate END) IS NULL THEN 0
ELSE COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN '12' THEN saledate END)
END AS CountDec
FROM trnsact
WHERE stype = 'p'
GROUP BY store, saledate, SumNov, SumDec, CountNov, CountDec
) AS T1
WHERE CountDec > 0 AND CountNov > 0
GROUP BY store, saledate, CountNov, CountDec, SumNov, SumDec, NovAvgRvn, DecAvgRvn
ORDER BY store;

The GROUP BY in the Derived Table is not doing aggregation on a month level, thus the COUNT(DISTINCT saledate)will be 1. You shouldn't use strings for numeric data (result of EXTRACT). You don't need the CASE(SUM) because COUNT never returns a NULL (you might use COALESCE instead):
I assume you want a query like this instead:
SELECT store,
-- if you only need the dates from Nov & Dec you can simply do
-- CountNov + CountDec instead
COUNT(DISTINCT saledate),
SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 11 THEN amt ELSE 0 END) AS SumNov,
SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 12 THEN amt ELSE 0 END) AS SumDec,
COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN 11 THEN saledate END) AS CountNov,
COUNT(DISTINCT CASE EXTRACT(MONTH FROM saledate) WHEN 12 THEN saledate END) AS CountDec,
(SumNov/CountNov) AS NovAvgRvn,
(SumDec/CountDec) AS DecAvgRvn
FROM trnsact
WHERE stype = 'p'
-- don't you need a condition to filter for a specific year/month?
AND EXTRACT(MONTH FROM saledate) IN (11,12)
GROUP BY store
ORDER BY store;

Related

User Attendance Date Year and Month Wise

I've a requirement to show user attendance year and month wise. Here is a sample
how it would look - Very basic:
Year - Jan - Feb
2018 - 26 - 20
2019 - 20 - 22
The data is retrieved from a single table and I tried the following query
to do so:
SELECT EXTRACT(YEAR FROM M.DATE) "YEAR",
COUNT(CASE WHEN EXTRACT(MONTH FROM M.DATE) = '1' THEN M.Id ELSE '-' END) "Jan",
COUNT(CASE WHEN EXTRACT(MONTH FROM M.DATE) = '2' THEN M.Id ELSE '-' END) "Feb"
FROM TABLE m
WHERE M.STATUS = 'P' AND M.Id = '12345678'
GROUP BY EXTRACT(YEAR FROM M.DATE) ORDER BY EXTRACT(YEAR FROM M.DATE);
Unfortunately this doesn't return the expected data, instead it shows the yearly
attendance of a user for each month as follows:
Year - Jan - Feb
2018 - 292 - 292
2019 - 100 - 100
Did I miss something here? Any ideas would be appreciated.
Try this-
SELECT EXTRACT(YEAR FROM M.DATE) "YEAR",
COUNT(CASE WHEN EXTRACT(MONTH FROM M.DATE) = '1' THEN M.Id ELSE NULL END) "Jan",
COUNT(CASE WHEN EXTRACT(MONTH FROM M.DATE) = '2' THEN M.Id ELSE NULL END) "Feb"
FROM TABLE m
WHERE M.STATUS = 'P' AND M.Id = '12345678'
GROUP BY EXTRACT(YEAR FROM M.DATE) ORDER BY EXTRACT(YEAR FROM M.DATE);
OR-
SELECT EXTRACT(YEAR FROM M.DATE) "YEAR",
SUM(CASE WHEN EXTRACT(MONTH FROM M.DATE) = '1' THEN 1 ELSE 0 END) "Jan",
SUM(CASE WHEN EXTRACT(MONTH FROM M.DATE) = '2' THEN 1 ELSE 0 END) "Feb"
FROM TABLE m
WHERE M.STATUS = 'P' AND M.Id = '12345678'
GROUP BY EXTRACT(YEAR FROM M.DATE) ORDER BY EXTRACT(YEAR FROM M.DATE);
I prefer using SUM() for this. But more importantly, your code is mixing types. EXTRACT() returns a number so the comparison should be to a number. I recommend:
SELECT EXTRACT(YEAR FROM M.DATE) as "YEAR",
SUM(CASE WHEN EXTRACT(MONTH FROM M.DATE) = 1 THEN 1 ELSE 0 END) as "Jan",
SUM(CASE WHEN EXTRACT(MONTH FROM M.DATE) = 2 THEN 1 ELSE 0 END) as "Feb"
FROM TABLE m
WHERE M.STATUS = 'P' AND
M.Id = 12345678 -- I am guessing that `id` is also a number
GROUP BY EXTRACT(YEAR FROM M.DATE)
ORDER BY EXTRACT(YEAR FROM M.DATE);
You should be careful mixing types. Conversions can impede the ability of the optimizer to find the best query plan.

how to do the program using subquery approach

SELECT SKU, SUM(CASE WHEN EXTRACT(MONTH FROM SALEDATE)=6 AND STYPE='P'
THEN AMT
END) AS VALUEJUNE,
SUM(CASE WHEN EXTRACT(MONTH FROM SALEDATE)=7 AND STYPE='P'
THEN AMT
END) AS VALUEJULY,
SUM(CASE WHEN EXTRACT(MONTH FROM SALEDATE)=8 AND STYPE='P'
THEN AMT
END) AS VALUEAUGUST
,(VALUEJUNE+VALUEJULY+VALUEAUGUST) AS totalsales
FROM TRNSACT
GROUP BY SKU
ORDER BY totalsales DESC ;
Put most of your query in a derived table, including the GROUP BY. Calculate totalsales on its result:
select sku, VALUEJUNE, VALUEJULY, VALUEAUGUST, (VALUEJUNE+VALUEJULY+VALUEAUGUST) AS totalsales
from
(
SELECT SKU,
SUM(CASE WHEN EXTRACT(MONTH FROM SALEDATE)=6 AND STYPE='P'
THEN AMT
END) AS VALUEJUNE,
SUM(CASE WHEN EXTRACT(MONTH FROM SALEDATE)=7 AND STYPE='P'
THEN AMT
END) AS VALUEJULY,
SUM(CASE WHEN EXTRACT(MONTH FROM SALEDATE)=8 AND STYPE='P'
THEN AMT
END) AS VALUEAUGUST
FROM TRNSACT
GROUP BY SKU
) dt
ORDER BY totalsales DESC ;

Is it possible to Count by diffrent condition in one query?

I have a Shipments table which basicly contains Shipments data with dates
id is integer
dateshipped is date
id dateshipped
1 1-JAN-16
2 1-JAN-16
3 3-FEB-16
4 9-FEB-16
I want to write a query which count all shipments based on Months.
What I should get is:
Jan Feb March....
2 2 0
I know I can do it by having query for each column, get only relevent rows for this specific month and just count them.
As follows:
Select (Select count(*)
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016 and EXTRACT(MONTH FROM dateshipped)::int=1 )as JAN,
(Select count(*)
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016 and EXTRACT(MONTH FROM dateshipped)::int=2 )as FEB
This works however its too much of the same code...
I am wondring if it is possible to do it with a single FROM statment and each column get it's own relevent rows for count.
Something like:
Select COL1,COL2,COL3...
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016;
and have something like:
COL1 = count only JAN records
COL2 = count only FEB records
....
maybe there is something with Parations on months or any other solution?
You need a pivot query to accomplish this:
SELECT SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 1 THEN 1 ELSE 0 END) AS Jan,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 2 THEN 1 ELSE 0 END) AS Feb,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 3 THEN 1 ELSE 0 END) AS Mar,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 4 THEN 1 ELSE 0 END) AS Apr,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 5 THEN 1 ELSE 0 END) AS May,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 6 THEN 1 ELSE 0 END) AS Jun,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 7 THEN 1 ELSE 0 END) AS Jul,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 8 THEN 1 ELSE 0 END) AS Aug,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 9 THEN 1 ELSE 0 END) AS Sep,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 10 THEN 1 ELSE 0 END) AS Oct,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 11 THEN 1 ELSE 0 END) AS Nov,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 12 THEN 1 ELSE 0 END) AS Dec
FROM Shipments
WHERE EXTRACT(YEAR FROM dateshipped)::int=2016
Since 9.4 you can use FILTER
SELECT
count(*) AS total,
count(*) FILTER (WHERE Extract(MONTH FROM dateshipped)::int=1) AS JAN,
count(*) FILTER (WHERE Extract(MONTH FROM dateshipped)::int=2) AS FEB,
...
FROM Shipments
WHERE Extract(YEAR FROM dateshipped)::int=2016;
Try case with sum function:
Select
sum(case when extract(MONTH from dateshipped)=1 then 1 else 0 end) as jan,
sum(case when extract(MONTH from dateshipped)=2 then 1 else 0 end) as feb,
sum(case when extract(MONTH from dateshipped)=3 then 1 else 0 end) as march
.....
.....
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016;

Re-Ordering the Months By Federal Fiscal Year

When running the following query I am trying to find a way to display the returned months by federal fiscal year instead of normal sequential value.
(ie I want to display months in the following order Oct, Nov, Dec, Jan, Feb, Mar, Apr, May Jun, Jul, Aug, Sept instead of Jan thru Dec.) Thanks
select wrkgrp,
sum (case when extract(month from reportdate) = 1 then 1 else 0 end) as January,
sum (case when extract(month from reportdate) = 2 then 1 else 0 end) as February,
sum (case when extract(month from reportdate) = 3 then 1 else 0 end) as March,
sum (case when extract(month from reportdate) = 4 then 1 else 0 end) as April,
sum (case when extract(month from reportdate) = 5 then 1 else 0 end) as May,
sum (case when extract(month from reportdate) = 6 then 1 else 0 end) as June,
sum (case when extract(month from reportdate) = 7 then 1 else 0 end) as July,
sum (case when extract(month from reportdate) = 8 then 1 else 0 end) as August,
sum (case when extract(month from reportdate) = 9 then 1 else 0 end) as September,
sum (case when extract(month from reportdate) = 10 then 1 else 0 end) as October,
sum (case when extract(month from reportdate) = 11 then 1 else 0 end) as November,
sum (case when extract(month from reportdate) = 12 then 1 else 0 end) as December,
from workorder
where reportdate between to_date ('2014-10-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
and to_date ('2015-09-30 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
and wrkgrp = 'PublicWorks'
group by 'wrkgrp;'
The fields will display in your results (horizontally) in the order you list them in your select statement. Structure your statement with Oct listed first like this:
select wrkgrp,
sum (case when extract(month from reportdate) = 10 then 1 else 0 end) as October,
sum (case when extract(month from reportdate) = 11 then 1 else 0 end) as November,
sum (case when extract(month from reportdate) = 12 then 1 else 0 end) as December,
sum (case when extract(month from reportdate) = 1 then 1 else 0 end) as January,
sum (case when extract(month from reportdate) = 2 then 1 else 0 end) as February,
sum (case when extract(month from reportdate) = 3 then 1 else 0 end) as March,
sum (case when extract(month from reportdate) = 4 then 1 else 0 end) as April,
sum (case when extract(month from reportdate) = 5 then 1 else 0 end) as May,
sum (case when extract(month from reportdate) = 6 then 1 else 0 end) as June,
sum (case when extract(month from reportdate) = 7 then 1 else 0 end) as July,
sum (case when extract(month from reportdate) = 8 then 1 else 0 end) as August,
sum (case when extract(month from reportdate) = 9 then 1 else 0 end) as September
from workorder
where reportdate between to_date ('2014-10-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss') ad to_date ('2015-09-30 00:00:00', 'yyyy/mm/dd hh24:mi:ss') and
wrkgrp = 'PublicWorks'
group by 'wrkgrp;'
Add case statements in your order by clause to get the desired sort.
ORDER BY
CASE WHEN extract(month from reportdate) = 10 THEN 1
CASE WHEN extract(month from reportdate) = 11 THEN 2
ASC

oracle sales total query

in a project i work at the moment we need to get monthly, quarterly and yearly sums of customer sales. i tried a query shown below which gets correct results for today. but i need to results for last years sale also. (last years monthly sale is that months sum)
i really need a fast fix here, thanks for every comment in advance
SELECT
CUSTOMER,
PRODUCT,
EXTRACT(MONTH FROM DAY) MONTH,
EXTRACT(YEAR FROM DAY) YEAR,
SUM(
CASE
WHEN DAY >= TRUNC(sysdate,'MM')
THEN DAILY_SALE
ELSE 0
END) AS MONTH_SALE,
SUM(
CASE
WHEN DAY >= add_months(TRUNC(sysdate,'MM'),-3)
AND DAY < TRUNC(sysdate,'MM')
THEN DAILY_SALE
ELSE 0
END) AS THREE_MONTHL_SALE,
SUM(
CASE
WHEN DAY >= add_months(TRUNC(sysdate,'MM'),-6)
AND DAY < TRUNC(sysdate,'MM')
THEN DAILY_SALE
ELSE 0
END) AS SIX_MONTHL_SALE,
SUM(
CASE
WHEN DAY >= add_months(TRUNC(sysdate,'MM'),-12)
AND DAY < TRUNC(sysdate,'MM')
THEN DAILY_SALE
ELSE 0
END) AS YEAR_SALE
FROM
SALES_TABLE
GROUP BY
CUSTOMER,
PRODUCT,
EXTRACT(MONTH FROM DAY),
EXTRACT(YEAR FROM DAY)
This may help be what you want... it gives you totals for every month and quarter, and for the entire year, for every year. I would recommend adding a "where EXTRACT(YEAR FROM DAY) = 2012" or similar clause if you want a particular year.
I believe this is what you asked for, but that is different than the sample you provided. The sample you gave provided trailing 3, 6, 9, and 12 month sales, which is not the same as quarters years and months. Still, you could easily mix and match if needed.
SELECT
CUSTOMER,
PRODUCT,
EXTRACT(YEAR FROM DAY) YEAR,
SUM(DAILY_SALE) as YEAR_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '01' THEN DAILY_SALE ELSE 0 END) AS MONTH_01_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '02' THEN DAILY_SALE ELSE 0 END) AS MONTH_02_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '03' THEN DAILY_SALE ELSE 0 END) AS MONTH_03_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '04' THEN DAILY_SALE ELSE 0 END) AS MONTH_04_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '05' THEN DAILY_SALE ELSE 0 END) AS MONTH_05_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '06' THEN DAILY_SALE ELSE 0 END) AS MONTH_06_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '07' THEN DAILY_SALE ELSE 0 END) AS MONTH_07_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '08' THEN DAILY_SALE ELSE 0 END) AS MONTH_08_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '09' THEN DAILY_SALE ELSE 0 END) AS MONTH_09_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '10' THEN DAILY_SALE ELSE 0 END) AS MONTH_10_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '11' THEN DAILY_SALE ELSE 0 END) AS MONTH_11_SALES,
SUM(CASE WHEN TO_CHAR(DAY, 'MM') = '12' THEN DAILY_SALE ELSE 0 END) AS MONTH_12_SALES,
SUM(
CASE
WHEN TO_CHAR(DAY, 'MM') IN ('10', '11', '12')
THEN DAILY_SALE
ELSE 0
END) AS Q4_SALES,
SUM(
CASE
WHEN TO_CHAR(DAY, 'MM') IN ('07', '08', '09')
THEN DAILY_SALE
ELSE 0
END) AS Q3_SALES,
SUM(
CASE
WHEN TO_CHAR(DAY, 'MM') IN ('04', '05', '06')
THEN DAILY_SALE
ELSE 0
END) AS Q2_SALES,
SUM(
CASE
WHEN TO_CHAR(DAY, 'MM') IN ('01', '02', '03')
THEN DAILY_SALE
ELSE 0
END) AS Q1_SALES,
FROM
SALES_TABLE
GROUP BY
CUSTOMER,
PRODUCT,
EXTRACT(YEAR FROM DAY)
This may not be exactly what you need but it may help:
select a.Product_Name,
d.Company_Name,
to_char(Order_Date, 'YYYY') as OrderYear,
sum(case to_char(c.Order_Date, 'Q') when '1'
then b.Unit_Price*b.Quantity*(1-b.Discount) else 0 end) "Qtr 1",
sum(case to_char(c.Order_Date, 'Q') when '2'
then b.Unit_Price*b.Quantity*(1-b.Discount) else 0 end) "Qtr 2",
sum(case to_char(c.Order_Date, 'Q') when '3'
then b.Unit_Price*b.Quantity*(1-b.Discount) else 0 end) "Qtr 3",
sum(case to_char(c.Order_Date, 'Q') when '4'
then b.Unit_Price*b.Quantity*(1-b.Discount) else 0 end) "Qtr 4"
from Products a
....
Also, look here for good examples of what you may need:
http://docs.oracle.com/html/B13915_04/appendix.htm#BEHJBJDE