oracle sales total query - sql

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

Related

SQL Query: A constant expression was encountered in the ORDER BY list

I'm getting the following error:
A constant expression was encountered in the ORDER BY list, position 1.
I'm trying to order by cell values in a column. The query is three union select statements. Code below:
Declare #RefDate date = '2019-09-04';
Select
'On Roll' as 'Student Group',
sum(case when year = '7' then 1 else 0 end) as 'Y7 No.', sum(case when year = '7' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y7 %',
sum(case when year = '8' then 1 else 0 end) as 'Y8 No.', sum(case when year = '8' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y8 %',
sum(case when year = '9' then 1 else 0 end) as 'Y9 No.', sum(case when year = '9' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y9 %',
sum(case when year = '10' then 1 else 0 end) as 'Y10 No.', sum(case when year = '10' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y10 %',
sum(case when year = '11' then 1 else 0 end) as 'Y11 No.', sum(case when year = '11' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y11 %',
sum(1) as 'All' from totals
where leaving is null and admission <= GETDATE() and enrolment in ('single registration','main - dual registration')
Union
Select
'New',
sum(case when year = '7' then 1 else 0 end) as 'Y7 No.', sum(case when year = '7' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y7 %',
sum(case when year = '8' then 1 else 0 end) as 'Y8 No.', sum(case when year = '8' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y8 %',
sum(case when year = '9' then 1 else 0 end) as 'Y9 No.', sum(case when year = '9' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y9 %',
sum(case when year = '10' then 1 else 0 end) as 'Y10 No.', sum(case when year = '10' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y10 %',
sum(case when year = '11' then 1 else 0 end) as 'Y11 No.', sum(case when year = '11' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y11 %',
sum(1) as 'All' from totals
where admission > #RefDate and enrolment in ('single registration','main - dual registration')
Union
Select
'Leavers',
sum(case when year = '7' then 1 else 0 end) as 'Y7 No.', sum(case when year = '7' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y7 %',
sum(case when year = '8' then 1 else 0 end) as 'Y8 No.', sum(case when year = '8' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y8 %',
sum(case when year = '9' then 1 else 0 end) as 'Y9 No.', sum(case when year = '9' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y9 %',
sum(case when year = '10' then 1 else 0 end) as 'Y10 No.', sum(case when year = '10' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y10 %',
sum(case when year = '11' then 1 else 0 end) as 'Y11 No.', sum(case when year = '11' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y11 %',
sum(1) as 'All' from totals
where leaving > #RefDate and enrolment in ('single registration','main - dual registration')
order by
case 'Student Group'
when 'On Roll' then 1
when 'New' then 2
when 'Leavers' then 3
end
If the groups were entirely separate, you could just use aggregation. Instead, you can use apply to define the groups and then aggregate:
Select v.Student_Group,
sum(case when year = '7' then 1 else 0 end) as 'Y7 No.', sum(case when year = '7' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y7 %',
sum(case when year = '8' then 1 else 0 end) as 'Y8 No.', sum(case when year = '8' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y8 %',
sum(case when year = '9' then 1 else 0 end) a s 'Y9 No.',
sum(case when year = '9' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y9 %',
sum(case when year = '10' then 1 else 0 end) as 'Y10 No.', sum(case when year = '10' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y10 %',
sum(case when year = '11' then 1 else 0 end) as 'Y11 No.', sum(case when year = '11' then 1 else 0 end)/cast(sum(1) as decimal) as 'Y11 %',
sum(1) as All
from totals t cross apply
(values (1, 'On Roll', case when leaving is null and admission <= GETDATE() then 1 end),
(2, 'New', case when admission > #RefDate then 1 end),
(3, 'Leaving', case when leaving > #RefDate then 1 end)
) v(ord, Student_Group, flag)
where enrolment in ('single registration', 'main - dual registration') and
v.flag = 1
group by v.which, v.ord
order by v.ord;
Resolved by using UNION ALL rather than UNION.
Hope this can help.
With t1 as (
Select leaving, admission, enrolment,
(case when year = '7' then 1 else 0 end) as Y7,
(case when year = '8' then 1 else 0 end) as Y8,
(case when year = '9' then 1 else 0 end) as Y9,
(case when year = '10' then 1 else 0 end) as Y10,
(case when year = '11' then 1 else 0 end) as Y11
From totals),
t2 as (
Select 1 as [Student Group], Y7, Y8, Y9, Y10, Y11
From t1
Where leaving is null and admission <= GETDATE() and enrolment in ('single registration','main - dual registration')
Union all
Select 2, Y7, Y8, Y9, Y10, Y11
From t1
Where admission > #RefDate and enrolment in ('single registration','main - dual registration')
Union all
Select 3, Y7, Y8, Y9, Y10, Y11
From t1
Where leaving > #RefDate and enrolment in ('single registration','main - dual registration'))
/* Select result */
Select case when [Student Group] = 1
then 'On Roll'
else case when [Student Group] = 2
then 'New'
else 'Leaving'
end
end as [Student Group Name],
sum(Y7) as [Y7 No.], 1.0 * sum(Y7) / count(1) as [Y7 %],
sum(Y8) as [Y8 No.], 1.0 * sum(Y8) / count(1) as [Y8 %],
sum(Y9) as [Y9 No.], 1.0 * sum(Y9) / count(1) as [Y9 %],
sum(Y10) as [Y10 No.], 1.0 * sum(Y10) / count(1) as [Y10 %],
sum(Y11) as [Y11 No.], 1.0 * sum(Y11) / count(1) as [Y11 %]
From t2
Group by [Student Group]
--Order by [Student Group]
Or
/* Select result */
Select StudentGroup.[Student Group Name],
t3.[Y7 No.], t3.[Y7 %],
t3.[Y8 No.], t3.[Y8 %],
t3.[Y9 No.], t3.[Y9 %],
t3.[Y10 No.], t3.[Y10 %],
t3.[Y11 No.], t3.[Y11 %]
From (
Select [Student Group],
sum(Y7) as [Y7 No.], 1.0 * sum(Y7) / count(1) as [Y7 %],
sum(Y8) as [Y8 No.], 1.0 * sum(Y8) / count(1) as [Y8 %],
sum(Y9) as [Y9 No.], 1.0 * sum(Y9) / count(1) as [Y9 %],
sum(Y10) as [Y10 No.], 1.0 * sum(Y10) / count(1) as [Y10 %],
sum(Y11) as [Y11 No.], 1.0 * sum(Y11) / count(1) as [Y11 %]
From t2
Group by [Student Group]
) t3
Inner join (
Select 1 as [Student Group], 'On Roll' as [Student Group Name]
Union
Select 2, 'New'
Union
Select 3, 'Leaving'
) StudentGroup
On t3.[Student Group] = StudentGroup.[Student Group]
Order by t3.[Student Group]
Cheers!

Not a Single Group Function in paid date

I have a oracle 11g sql code to show weekly report, but getting error ORA-00937: not a single-group group function .
and the error cursor pointed to first line the PAID_DATE => TO_CHAR(PAID_DATE, 'YEAR') "YEAR",
SELECT
TO_CHAR(PAID_DATE, 'YEAR') "YEAR",
TO_CHAR(PAID_DATE, 'MONTH') "MONTH",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '1' AND TO_CHAR(PAID_DATE, 'DD') <=7 THEN TOTAL_PAID ELSE 0 END) "MINGGU1",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '8' AND TO_CHAR(PAID_DATE, 'DD') <=15 THEN TOTAL_PAID ELSE 0 END) "MINGGU2",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '16' AND TO_CHAR(PAID_DATE, 'DD') <=23 THEN TOTAL_PAID ELSE 0 END) "MINGGU3",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '24' THEN TOTAL_PAID ELSE 0 END) "MINGGU4"
FROM
PAID_TABLE
You should add a GROUP BY clause to specify the columns you are grouping by:
SELECT
TO_CHAR(PAID_DATE, 'YEAR') "YEAR",
TO_CHAR(PAID_DATE, 'MONTH') "MONTH",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '1' AND TO_CHAR(PAID_DATE, 'DD') <=7 THEN TOTAL_PAID ELSE 0 END) "MINGGU1",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '8' AND TO_CHAR(PAID_DATE, 'DD') <=15 THEN TOTAL_PAID ELSE 0 END) "MINGGU2",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '16' AND TO_CHAR(PAID_DATE, 'DD') <=23 THEN TOTAL_PAID ELSE 0 END) "MINGGU3",
SUM(CASE WHEN TO_CHAR(PAID_DATE, 'D') >= '24' THEN TOTAL_PAID ELSE 0 END) "MINGGU4"
FROM
PAID_TABLE
GROUP BY TO_CHAR(PAID_DATE, 'YEAR'), TO_CHAR(PAID_DATE, 'MONTH') -- added line
You are missing the GROUP BY. However, I wouldn't recommend doing string comparisons for day of the month.
Instead:
SELECT TO_CHAR(PAID_DATE, 'YEAR MONTH') as YEAR_MONTH,
SUM(CASE WHEN EXTRACT(DAY FROM PAIDDATE) BETWEEN 1 AND 7 THEN TOTAL_PAID ELSE 0 END) as MINGGU1,
SUM(CASE WHEN EXTRACT(DAY FROM PAIDDATE) BETWEEN 8 AND 15 THEN TOTAL_PAID ELSE 0 END) as MINGGU2,
SUM(CASE WHEN EXTRACT(DAY FROM PAIDDATE) BETWEEN 16 AND 23 THEN TOTAL_PAID ELSE 0 END) as MINGGU3,
SUM(CASE WHEN EXTRACT(DAY FROM PAIDDATE) >= 24 THEN TOTAL_PAID ELSE 0 END) as MINGGU4
FROM PAID_TABLE
GROUP BY TO_CHAR(PAID_DATE, 'YEAR MONTH')
ORDER BY MIN(PAID_DATE);
Note that this also combines the first two columns into a single column. If you are going to write out the date as strings, one column makes sense to me (although I prefer the 'YYYY-MM' format).
I added an ORDER BY so the rows are returned chronologically.

SQL Query for count by month over multiple years

I've been using the query below to get me a count of records by month. Works good for a specific year.
However, its a bit of a pain if I want to compare a count from Jan 2018 to Jan 2019. Especially if I want to graph it.
How might I adjust this so that I could get a Jan 18, Feb 18,....Jan 19 type of result by giving a span of years.
This is Postgres 9.6
Thanks!
SELECT
count(case when to_char(t.order_date, 'MM') = '01' then 1 END) as Jan,
count(case when to_char(t.order_date, 'MM') = '02' then 1 END) as Feb,
count(case when to_char(t.order_date, 'MM') = '03' then 1 END) as Mar,
count(case when to_char(t.order_date, 'MM') = '04' then 1 END) as Apr,
count(case when to_char(t.order_date, 'MM') = '05' then 1 END) as May,
count(case when to_char(t.order_date, 'MM') = '06' then 1 END) as June,
count(case when to_char(t.order_date, 'MM') = '07' then 1 END) as Jul,
count(case when to_char(t.order_date, 'MM') = '08' then 1 END) as Aug,
count(case when to_char(t.order_date, 'MM') = '09' then 1 END) as Sep,
count(case when to_char(t.order_date, 'MM') = '10' then 1 END) as Oct,
count(case when to_char(t.order_date, 'MM') = '11' then 1 END) as Nov,
count(case when to_char(t.order_date, 'MM') = '12' then 1 END) as Dec
FROM transactions as t
WHERE to_char(t.order_date, 'YYYY') = '2019'
You can make “buckets” of your data by timestamp, by combining:
Truncate a timestamp value to a specified precision, flattening those values to a single value.
Group by the resulting lower-precision values.
SELECT
date_trunc('month', t.order_date) AS order_month,
count(t.order_id) AS count
FROM transaction AS t
GROUP BY order_month
ORDER BY order_month
Then it's up to you what years to limit the result to:
SELECT
date_trunc('month', t.order_date) AS order_month,
count(t.order_id) AS count
FROM transaction AS t
WHERE
date_part('year', t.order_date) = 2019
GROUP BY order_month
ORDER BY order_month
Please check below query, is this relevant?
Blockquote
SELECT
to_char(order_date, 'YYYY'),
count(case when to_char(t.order_date, 'MM') = '01' then 1 END) as Jan,
count(case when to_char(t.order_date, 'MM') = '02' then 1 END) as Feb,
count(case when to_char(t.order_date, 'MM') = '03' then 1 END) as Mar,
count(case when to_char(t.order_date, 'MM') = '04' then 1 END) as Apr,
count(case when to_char(t.order_date, 'MM') = '05' then 1 END) as May,
count(case when to_char(t.order_date, 'MM') = '06' then 1 END) as June,
count(case when to_char(t.order_date, 'MM') = '07' then 1 END) as Jul,
count(case when to_char(t.order_date, 'MM') = '08' then 1 END) as Aug,
count(case when to_char(t.order_date, 'MM') = '09' then 1 END) as Sep,
count(case when to_char(t.order_date, 'MM') = '10' then 1 END) as Oct,
count(case when to_char(t.order_date, 'MM') = '11' then 1 END) as Nov,
count(case when to_char(t.order_date, 'MM') = '12' then 1 END) as Dec
FROM transactions as t where to_char(order_date, 'YYYY') in ('2018','2019')
group by to_char(order_date, 'YYYY');
Blockquote
Do you want the results on different rows?
SELECT to_char(t.order_date, 'YYYY') = '2019',
count(*) filter (to_char(t.order_date, 'MM') = '01') as Jan,
count(*) filter (to_char(t.order_date, 'MM') = '02') as Feb,
. . .
count(*) filter (to_char(t.order_date, 'MM') = '12') as Dec
FROM transactions as t
GROUP BY to_char(t.order_date, 'YYYY') = '2019'

return a zero for month with zero rows using case extract sql

Trying to list last 12 months counting records in each month and want to include months where no record was found to display 0 next to that month name. I tried including another table that would always have at least one record for all 12 months and case extract the month from their but I know I'm doing this wrong. All the research I did, didn't use case extract and I'm looking to keep it if I can.. open to if i cannot.
Current query works and is:
select count(RMA.id) "Number of RMAs", case extract(month from
RMA.RMA_DATE)when 1 then 'January'
when 2 then 'February'
when 3 then 'March'
when 4 then 'April'
when 5 then 'May'
when 6 then 'June'
when 7 then 'July'
when 8 then 'August'
when 9 then 'September'
when 10 then 'October'
when 11 then 'November'
when 12 then 'December'
else 'error'
end, extract(year from RMA.rma_date)
from RMA,
RMA_DETAIL
where RMA.ID = RMA_DETAIL.RMA_ID And
RMA.rma_date >= sysdate - 365 And
RMA_DETAIL.ID <> 3
group by extract(month from RMA.rma_date), extract(year from RMA.rma_date)
order by extract(year from RMA.rma_date), extract(month from RMA.rma_date)
results
SUM Cases
If you're already fine with identifying the months in the query, it might be worth just summing these up. A count can only count what's in the table. If you sum up the instances of appearance, you'll get a sum of 0 where your months don't appear. Consider something like this:
SELECT
SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '1' THEN 1 ELSE 0) AS January
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '2' THEN 1 ELSE 0) AS February
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '3' THEN 1 ELSE 0) AS March
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '4' THEN 1 ELSE 0) AS April
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '5' THEN 1 ELSE 0) AS May
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '6' THEN 1 ELSE 0) AS June
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '7' THEN 1 ELSE 0) AS July
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '8' THEN 1 ELSE 0) AS August
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '9' THEN 1 ELSE 0) AS September
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '10' THEN 1 ELSE 0) AS October
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '11' THEN 1 ELSE 0) AS November
,SUM(CASE WHEN EXTRACT(month from RMA.RMA_DATE) = '12' THEN 1 ELSE 0) AS December
...

Error with group by statement?

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;