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.
Related
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!
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'
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;
I have a table like:
ID TIMEVALUE
----- -------------
1 06.07.15 06:43:01,000000000
2 06.07.15 12:17:01,000000000
3 06.07.15 18:21:01,000000000
4 06.07.15 23:56:01,000000000
5 07.07.15 04:11:01,000000000
6 07.07.15 10:47:01,000000000
7 07.07.15 12:32:01,000000000
8 07.07.15 14:47:01,000000000
and I want to group this data by special times.
My current query looks like this:
SELECT TO_CHAR(TIMEVALUE, 'YYYY\MM\DD'), COUNT(ID),
SUM(CASE WHEN TO_CHAR(TIMEVALUE, 'HH24MI') <=700 THEN 1 ELSE 0 END) as morning,
SUM(CASE WHEN TO_CHAR(TIMEVALUE, 'HH24MI') >700 AND TO_CHAR(TIMEVALUE, 'HH24MI') <1400 THEN 1 ELSE 0 END) as daytime,
SUM(CASE WHEN TO_CHAR(TIMEVALUE, 'HH24MI') >=1400 THEN 1 ELSE 0 END) as evening FROM Table
WHERE TIMEVALUE >= to_timestamp('05.07.2015','DD.MM.YYYY')
GROUP BY TO_CHAR(TIMEVALUE, 'YYYY\MM\DD')
and I am getting this output
day overall morning daytime evening
----- ---------
2015\07\05 454 0 0 454
2015\07\06 599 113 250 236
2015\07\07 404 139 265 0
so that is fine grouping on the same day (0-7 o'clock, 7-14 o'clock and 14-24 o'clock)
But my question now is:
How can I group over midnight?
For example count from 6-14 , 14-23 and 23-6 o'clock on next day.
I hope you understand my question. You are welcome to even improve my upper query if there is a better solution.
EDIT: It is tested now: SQL Fiddle
The key is simply to adjust the group by so that anything before 6am gets grouped with the previous day. After that, the counts are pretty straight-forward.
SELECT TO_CHAR(CASE WHEN EXTRACT(HOUR FROM timevalue) < 6
THEN timevalue - 1
ELSE timevalue
END, 'YYYY\MM\DD') AS day,
COUNT(*) AS overall,
SUM(CASE WHEN EXTRACT(HOUR FROM timevalue) >= 6 AND EXTRACT(HOUR FROM timevalue) < 14
THEN 1 ELSE 0 END) AS morning,
SUM(CASE WHEN EXTRACT(HOUR FROM timevalue) >= 14 AND EXTRACT(HOUR FROM timevalue) < 23
THEN 1 ELSE 0 END) AS daytime,
SUM(CASE WHEN EXTRACT(HOUR FROM timevalue) < 6 OR EXTRACT(HOUR FROM timevalue) >= 23
THEN 1 ELSE 0 END) AS evening
FROM my_table
WHERE timevalue >= TO_TIMESTAMP('05.07.2015','DD.MM.YYYY')
GROUP BY TO_CHAR(CASE WHEN EXTRACT(HOUR FROM timevalue) < 6
THEN timevalue - 1
ELSE timevalue
END, 'YYYY\MM\DD');
Substract 1 day from timevalue for times lower than '06:00' at first and then:
SQLFiddle demo
select TO_CHAR(day, 'YYYY\MM\DD') day, COUNT(ID) cnt,
SUM(case when '23' < tvh or tvh <= '06' THEN 1 ELSE 0 END) as midnight,
SUM(case when '06' < tvh and tvh <= '14' THEN 1 ELSE 0 END) as daytime,
SUM(case when '14' < tvh and tvh <= '23' THEN 1 ELSE 0 END) as evening
FROM (
select id, to_char(TIMEVALUE, 'HH24') tvh,
trunc(case when (to_char(timevalue, 'hh24') <= '06')
then timevalue - interval '1' day
else timevalue end) day
from t1
)
GROUP BY day
Maybe you can do it like this (with some reformatting or PIVOT):
WITH spans AS
(SELECT TIMESTAMP '2015-01-01 00:00:00' + LEVEL * INTERVAL '1' HOUR AS start_time
FROM dual
CONNECT BY TIMESTAMP '2015-01-01 00:00:00' + LEVEL * INTERVAL '1' HOUR < LOCALTIMESTAMP),
t AS
(SELECT start_time, lead(start_time, 1) OVER (ORDER BY start_time) AS end_time, ROWNUM AS N
FROM spans
WHERE EXTRACT(HOUR FROM start_time) IN (6,14,23))
SELECT N, start_time, end_time, COUNT(*) AS ID_COUNT,
DECODE(EXTRACT(HOUR FROM start_time), 6,'morning', 14,'daytime', 23,'evening') AS daytime
FROM t
JOIN YOUR_TABLE WHERE TIMEVALUE BETWEEN start_time AND end_time
GROUP BY N;
Of course, the initial time value ('2015-01-01 00:00:00' in my example) has to be lower than the least date in your table.
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