select multiple rows group by date interval ( causes duplicates) [duplicate] - sql

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

SQL (Redshift) error when using case when - this type of correlated subquery pattern is not supported

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.

Sum Based on Date

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

Postgres query to get data datewise

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.

How to change row value into column header

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.

SQL Results group by month

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 )