This question already has answers here:
retrieve multible columns group by date intervall
(2 answers)
Closed 2 years ago.
I'm trying to retrieve weight data summed over the first 15 days of a month and another 15 days of that month.
Like the table below .
here is my code,
SELECT * from
( select SUM(B.SCALE_WEIGHT) as Mtrl1 FROM TRACK2.LOG2_TAB B
where B.SCALE_EVENTDATE >= date '2020-09-01'
and B.SCALE_EVENTDATE < date '2020-09-30'
AND B.Scale_EVENTDATE = B.SCALE_EVENTDATE
and MTRLID_EXT = 206
group by floor(extract(day from SCALE_EVENTDATE)/16) ) ,
( select SUM(B.SCALE_WEIGHT) as Mtrl2 FROM TRACK2.LOG2_TAB B
where B.SCALE_EVENTDATE >= date '2020-09-01'
and B.SCALE_EVENTDATE < date '2020-09-30'
AND B.Scale_EVENTDATE = B.SCALE_EVENTDATE
and MTRLID_EXT = 211
group by floor(extract(day from SCALE_EVENTDATE)/16) )
but the result is shown in the image below, the data is duplicated ! and missing Date column
I think you want conditional aggregation:
select
floor(extract(day from scale_eventdate)/16) as fortnight,
sum(case when mtrlid_ext = 206 then scale_weight else 0 end) as mtrl1,
sum(case when mtrlid_ext = 211 then scale_weight else 0 end) as mtrl2
from track2.log2_tab
where
mtrlid_ext in (206, 211)
and scale_eventdate >= date '2020-09-01'
and scale_eventdate < date '2020-10-01'
group by floor(extract(day from scale_eventdate) / 16)
Note that I fixed the date filtering; if you want the entire month of September, then the second condition should be: < date '2020-10-01'.
Related
I'm trying to return a couple of 'average if' columns using the following:
select
date,
avg(case when hour >= 23 or hour <= 6) then (select price) else null end) as price1,
avg(case when (hour >= 16 and hour <= 18) then (select price) else null end) as price2
from
xxxxxxxxx
where
date <= '2019-12-31' and
date >= '2018-12-01'
group by
date
order by
date
it works when I use each avg(case when) individually but when I use them both I get the error
Invalid operation: This type of correlated subquery pattern is not supported due to internal error
Why the select in the select?
select date,
avg(case when hour >= 23 or hour <= 6 then price end) as price1,
avg(case when hour >= 16 and hour <= 18 then price end) as price2
from xxxxxxxxx
where date <= '2019-12-31' and
date >= '2018-12-01'
group by date
order by date;
The else null is also redundant.
I currently have this code that I want to sum every quantity based on the year. I have written a code that I thought would sum all the charges in 2016 and 2017, but it isn't running correctly.
I added the two different types of partition by statements to test and see if either would work and they don't. When I take them out, the Annual column just shows me the quantity for that specific receipt.
Here is my current code:
SELECT
ReceiptNumber
,Quantity
,Date
,sum(CASE WHEN (Date >= '2016-01-01' and Date < '2017-01-01') THEN
Quantity
ELSE 0 END)
OVER (PARTITION BY Date)
as Annual2016
,sum(CASE WHEN (Date >= '2017-01-01' and Date < '2018-01-01') THEN
Quantity
ELSE 0 END)
OVER (PARTITION BY ReceiptNumber)
as Annual2017
FROM Table1
GROUP BY ReceiptNumber, Quantity, Date
I would like my data to look like this
ReceiptNumber Quantity Date Annual2016 Annual2017
1 5 2016-01-05 17 13
2 11 2017-04-03 17 13
3 12 2016-11-11 17 13
4 2 2017-09-09 17 13
Here is a sample of some of the data I am pulling from:
ReceiptNumber Quantity Date
1 5 2016-01-05
2 11 2017-04-03
3 12 2016-11-11
4 2 2017-09-09
5 96 2015-07-08
6 15 2016-12-12
7 24 2016-04-19
8 31 2017-01-02
9 10 2017-0404
10 18 2015-10-10
11 56 2017-06-02
Try something like this
Select
..
sum(CASE WHEN (Date >= '2016-01-01' and Date < '2017-01-01') THEN
Quantity
ELSE 0 END)
OVER () as Annual2016
sum(CASE WHEN (Date >= '2017-01-01' and Date < '2018-01-01') THEN
Quantity
ELSE 0 END)
OVER ()as Annual2017
..
Where Date >= '2016-01-01' and Date < '2018-01-01'
If you want it printed only once at the top then you should run it in a separate query like:
SELECT YEAR(Date) y, sum(Quantity) s FROM Table1 GROUP BY YEAR(Date)
and then do the main query like this:
SELECT * FROM table1
Easy, peasey ... ;-)
Your original question could also be answered with:
SELECT *,
(SELECT SUM(Quantity) FROM Table1 WHERE YEAR(Date)=2016 ) Annual2016,
(SELECT SUM(Quantity) FROM Table1 WHERE YEAR(Date)=2017 ) Annual2017
FROM table1
You need some conditional aggreation over a Window Aggregate. Simply remove both PARTITION BY as you're already filtering the year in the CASE:
SELECT
ReceiptNumber
,Quantity
,Date
,sum(CASE WHEN (Date >= '2016-01-01' and Date < '2017-01-01') THEN
Quantity
ELSE 0 END)
OVER () as Annual2016
,sum(CASE WHEN (Date >= '2017-01-01' and Date < '2018-01-01') THEN
Quantity
ELSE 0 END)
OVER () as Annual2017
FROM Table1
You probably don't need the final GROUP BY ReceiptNumber, Quantity, Date
I am using PostgreSQL.
I have a table like below:
ID product_id Date Qty
-----------------------------------
1 12 2008-06-02 50
2 3 2008-07-12 5
3 12 2009-02-10 25
4 10 2012-11-01 22
5 2 2011-03-25 7
Now I want the result like below (i.e product wise sum of qty field of last 4 years):
product_id
QTY(current_year)
QTY( current year + last_year)
QTY_last2_years
QTY > 2 years
SELECT product_id
,sum(CASE mydate >= x.t THEN qty END) AS qty_current_year
,sum(CASE mydate >= (x.t - interval '1 y') THEN qty END) AS qty_since_last_year
,sum(CASE mydate >= (x.t - interval '2 y')
AND mydate < x.t THEN qty END) AS qty_last_2_year
,sum(CASE mydate < (x.t - interval '2 y') THEN qty END) AS qty_older
FROM tbl
CROSS JOIN (SELECT date_trunc('year', now()) AS t) x -- calculate once
GROUP BY 1;
To resuse the calculated beginning of the current year I CROSS JOIN it as subquery x.
select
extract(year from datetimestamp ) Yr,extract(month from datetimestamp) Mn,
c.weekday_of_month wk, a.aircraft_type,count( a.aircraft_type) from fcm_bv.Flights b
join fcm_bv.Fleet a on b.aircraftid=a.tail
join SYS_CALENDAR.CALENDAR c
on cast(b.datetimestamp AS DATE FORMAT 'YYYY-MM-DD') = cast(c.calendar_date AS DATE FORMAT 'YYYY-MM-DD')
where cast(datetimestamp as date) >= '2011-09-01'
and cast(datetimestamp as date) <= '2011-09-30' order by wk
group by Yr,Mn,wk,a.fleet,a.aircraft_type
While Running above Query I am getting out put like this
Yr Mn wk AIRCRAFT_TYPE Count(AIRCRAFT_TYPE)
2011 9 1 B737-700 1744
2011 9 1 B737-800 131
2011 9 1 B737-800W 2711
2011 9 1 B737-8BK 180
2011 9 1 B737-700W 329
But I need output in below format
Yr Mn wk B737-700 B737-800 B737-800W B737-8BK B737-700W
2011 9 1 1744 131 2711 180 329
Could any one help me
In the past when I have needed to do this the pivot was against a discrete, managable volume of categories and the following SQL has served me well:
SELECT EXTRACT(YEAR FROM b.datetimestamp) AS Yr
, EXTRACT(MONTH FROM b.datetimestamp) AS Mn
, C.weekday_of_month
, COUNT(CASE WHEN a.aircraft_type = 'B737-700' THEN a.aircraft_type ELSE NULL END) AS B737-700
, COUNT(CASE WHEN a.aircraft_type = 'B737-800' THEN a.aircraft_type ELSE NULL END) AS B737-800
, /* Other Known Aircrafts */
, COUNT(CASE WHEN a.aircrat_type NOT IN ('<list of known aircraft types>') THEN a.aircraft_type ELSE NULL END) AS Uncategorized_Aircraft
FROM fcm_bv.Flights b
join fcm_bv.Fleet a on b.aircraftid=a.tail
join SYS_CALENDAR.CALENDAR c
on cast(b.datetimestamp AS DATE FORMAT 'YYYY-MM-DD') = cast(c.calendar_date AS DATE FORMAT 'YYYY-MM-DD')
WHERE cast(datetimestamp as date) >= '2011-09-01'
AND cast(datetimestamp as date) <= '2011-09-30' order by wk
GROUP BY Yr,Mn,wk,a.fleet
If you have to pivot against a constantly changing category it may be best to leave the pivoting to MS Excel or BI tool of choice.
Hope this helps.
I'm trying to return some results spread over a rolling 12 month period eg:
MONTH IN OUT
January 210 191
February 200 111
March 132 141
April 112 141
May 191 188
etc...
How do I spread the results over a date range, populating the first column with the month name?
IN MSSQL it would be something like:
SELECT COUNT(problem.problem_type = 'IN') AS IN,
COUNT(problem.problem_type = 'OUT') AS OUT,
DATEPART(year, DateTime) as Year,
DATEPART(month, DateTime) as Month
FROM problem
WHERE (DateTime >= dbo.FormatDateTime('2010-01-01'))
AND
(DateTime < dbo.FormatDateTime('2010-01-31'))
GROUP BY DATEPART(year, DateTime),
DATEPART(month, DateTime);
But this is against an Oracle database so DATEPART and DateTime are not available.
My Problem table is roughly:
problem_ID Problem_type IN_Date OUT_Date
1 IN 2010-01-23 16:34:29.0 2010-02-29 13:06:28.0
2 IN 2010-01-27 12:34:29.0 2010-01-29 12:01:28.0
3 OUT 2010-02-13 13:24:29.0 2010-09-29 15:04:28.0
4 OUT 2010-02-15 16:31:29.0 2010-07-29 11:03:28.0
Use:
SELECT SUM(CASE WHEN p.problem_type = 'IN' THEN 1 ELSE 0 END) AS IN,
SUM(CASE WHEN p.problem_type = 'OUT' THEN 1 ELSE 0 END) AS OUT,
TO_CHAR(datetime, 'YYYY') AS year,
TO_CHAR(datetime, 'MM') AS month
FROM PROBLEM p
WHERE p.DateTime >= TO_DATE('2010-01-01', 'YYYY-MM-DD')
AND p.DateTime < TO_DATE('2010-01-31', 'YYYY-MM-DD')
GROUP BY TO_CHAR(datetime, 'YYYY'), TO_CHAR(datetime, 'MM')
You could also use:
SELECT SUM(CASE WHEN p.problem_type = 'IN' THEN 1 ELSE 0 END) AS IN,
SUM(CASE WHEN p.problem_type = 'OUT' THEN 1 ELSE 0 END) AS OUT,
TO_CHAR(datetime, 'MM-YYYY') AS mon_year
FROM PROBLEM p
WHERE p.DateTime >= TO_DATE('2010-01-01', 'YYYY-MM-DD')
AND p.DateTime < TO_DATE('2010-01-31', 'YYYY-MM-DD')
GROUP BY TO_CHAR(datetime, 'MM-YYYY')
Reference:
TO_CHAR
TO_DATE
You probably want something like
SELECT SUM( (CASE WHEN problem_type = 'IN' THEN 1 ELSE 0 END) ) in,
SUM( (CASE WHEN problem_type = 'OUT' THEN 1 ELSE 0 END) ) out,
EXTRACT( year FROM DateTime ) year,
EXTRACT( month FROM DateTime ) month
FROM problem
WHERE DateTime >= date '2010-01-01'
AND DateTime < date '2010-01-31'
GROUP BY EXTRACT( year FROM DateTime ),
EXTRACT( month FROM DateTime )