We need to count the number of items that occur 10 minutes before and 10 minutes after the hour, by day. We have a table that tracks the items individually. Ideally i would like to have the output be something like the below, but and totally open to other suggestions.
Table - Attendance
Att_item timestamp
1 2012-09-12 18:08:00
2 2012-09-01 23:26:00
3 2012-09-23 09:33:00
4 2012-09-11 09:43:00
5 2012-09-06 05:57:00
6 2012-09-17 19:26:00
7 2012-09-06 10:51:00
8 2012-09-19 09:42:00
9 2012-09-06 13:55:00
10 2012-09-05 07:26:00
11 2012-09-02 03:08:00
12 2012-09-19 12:17:00
13 2012-09-12 18:14:00
14 2012-09-12 18:14:00
Output
Date Timeslot_5pm Timeslot_6pm Timeslot_7pm
9/11/2012 11 22 22
9/12/2012 30 21 55
9/13/2012 44 33 44
Your requirements are not totally clear, but if you only want to count the number of records in the 20 minute window:
select cast(tstmp as date) date,
sum(case when datepart(hour, tstmp) = 1 then 1 else 0 end) Timeslot_1am,
sum(case when datepart(hour, tstmp) = 2 then 1 else 0 end) Timeslot_2am,
sum(case when datepart(hour, tstmp) = 3 then 1 else 0 end) Timeslot_3am,
sum(case when datepart(hour, tstmp) = 4 then 1 else 0 end) Timeslot_4am,
sum(case when datepart(hour, tstmp) = 5 then 1 else 0 end) Timeslot_5am,
sum(case when datepart(hour, tstmp) = 6 then 1 else 0 end) Timeslot_6am,
sum(case when datepart(hour, tstmp) = 7 then 1 else 0 end) Timeslot_7am,
sum(case when datepart(hour, tstmp) = 8 then 1 else 0 end) Timeslot_8am,
sum(case when datepart(hour, tstmp) = 9 then 1 else 0 end) Timeslot_9am,
sum(case when datepart(hour, tstmp) = 10 then 1 else 0 end) Timeslot_10am,
sum(case when datepart(hour, tstmp) = 11 then 1 else 0 end) Timeslot_11am,
sum(case when datepart(hour, tstmp) = 12 then 1 else 0 end) Timeslot_12pm,
sum(case when datepart(hour, tstmp) = 13 then 1 else 0 end) Timeslot_1pm,
sum(case when datepart(hour, tstmp) = 14 then 1 else 0 end) Timeslot_2pm,
sum(case when datepart(hour, tstmp) = 15 then 1 else 0 end) Timeslot_3pm,
sum(case when datepart(hour, tstmp) = 16 then 1 else 0 end) Timeslot_4pm,
sum(case when datepart(hour, tstmp) = 17 then 1 else 0 end) Timeslot_5pm,
sum(case when datepart(hour, tstmp) = 18 then 1 else 0 end) Timeslot_6pm,
sum(case when datepart(hour, tstmp) = 19 then 1 else 0 end) Timeslot_7pm,
sum(case when datepart(hour, tstmp) = 20 then 1 else 0 end) Timeslot_8pm,
sum(case when datepart(hour, tstmp) = 21 then 1 else 0 end) Timeslot_9pm,
sum(case when datepart(hour, tstmp) = 22 then 1 else 0 end) Timeslot_10pm,
sum(case when datepart(hour, tstmp) = 23 then 1 else 0 end) Timeslot_11pm
from yourtable
where datepart(minute, tstmp) >= 50
or datepart(minute, tstmp) <= 10
group by cast(tstmp as date)
If you want to count the number of records within each hour plus the records that are in the >=50 and <= 10 timeframe, then you will have to adjust this.
This does just one column (well 4 but you get my point).
select DATEPART(YYYY, FTSdate) as [year], DATEPART(mm, FTSdate) as [month]
, DATEPART(dd, FTSdate) as [day], DATEPART(hh, FTSdate) as [hour], COUNT(*)
from [Gabe2a].[dbo].[docSVsys]
where DATEPART(mi, FTSdate) >= 50 or DATEPART(mi, FTSdate) <= 10
group by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate), DATEPART(hh, FTSdate)
order by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate), DATEPART(hh, FTSdate)
Separate columns.
select DATEPART(YYYY, FTSdate) as [year], DATEPART(mm, FTSdate) as [month]
, DATEPART(dd, FTSdate) as [day]
, sum(case when DATEPART(hh, FTSdate) = '0' then 1 else 0 end) as [0:00] -- midnight
, sum(case when DATEPART(hh, FTSdate) = '1' then 1 else 0 end) as [1:00]
, sum(case when DATEPART(hh, FTSdate) = '2' then 1 else 0 end) as [2:00]
, sum(case when DATEPART(hh, FTSdate) = '3' then 1 else 0 end) as [3:00]
, sum(case when DATEPART(hh, FTSdate) = '4' then 1 else 0 end) as [4:00]
from [Gabe2a].[dbo].[docSVsys]
where DATEPART(mi, FTSdate) >= 50 or DATEPART(mi, FTSdate) <= 10
group by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate)
order by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate)
Related
I have a rollup SQL statement that I'm trying to covert over from Oracle into PostGresSql. Overall the results look correct except I'm getting a blank value in the grouping column and I'm not sure how to get rid of it.
Right now I have:
SELECT
COALESCE(CASE WHEN GROUPING(COUNTY) = 1 THEN 'TOTAL' else county::text END) as COUNTY
,COUNT(CASE WHEN STV_TO_GAS THEN 1 END) as STOVE_TO_GAS_SUM
,COUNT(CASE WHEN FIRE_TO_GAS THEN 1 END) as FIRE_TO_GAS_SUM
,COUNT(CASE WHEN PELLET_TO_GAS THEN 1 END) as PELLET_TO_GAS_SUM
,COUNT(CASE WHEN STV_TO_ELECTRIC THEN 1 END) as STOVE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN FIRE_TO_ELECTRIC THEN 1 END) as FIRE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN PELLET_TO_ELECTRIC THEN 1 END) as PELLET_TO_ELECTRIC_SUM
,COUNT(CASE WHEN MERIDIAN THEN 1 END) as WITHIN_MERIDIAN_SUM
,count(CASE WHEN hb357.stv_to_gas then 1 END) +
count(CASE WHEN hb357.fire_to_gas then 1 END) +
count(CASE WHEN hb357.pellet_to_gas then 1 END) +
count(CASE WHEN hb357.stv_to_electric then 1 END) +
count(CASE WHEN hb357.fire_to_electric then 1 END) +
count(CASE WHEN hb357.pellet_to_electric then 1 END) +
count(CASE WHEN hb357.meridian then 1 END ) AS county_totals
FROM woodburn.HB357
WHERE app_status IN ('pending','approved')
AND (COUNTY IS NOT NULL OR trim(COUNTY) <> '')
GROUP BY rollup (county)
but its still returning a blank value in the county column
I've also trued changing the first case statement to
COALESCE(CASE
WHEN GROUPING(COUNTY) = 1 THEN 'TOTAL'
WHEN TRIM(COUNTY) != '' AND COUNTY IS NOT NULL then county
END) as COUNTY
but its returning a null row for county
FINAL SOLUTION
After trying all things suggested I essentially implemented what Jorge Campos recommended by doing the following:
SELECT
COALESCE(CASE
WHEN GROUPING(COUNTY) = 1 THEN 'TOTAL'
WHEN TRIM(COUNTY) != '' then county
END) as COUNTY
,COUNT(CASE WHEN STV_TO_GAS THEN 1 END) as STOVE_TO_GAS_SUM
,COUNT(CASE WHEN FIRE_TO_GAS THEN 1 END) as FIRE_TO_GAS_SUM
,COUNT(CASE WHEN PELLET_TO_GAS THEN 1 END) as PELLET_TO_GAS_SUM
,COUNT(CASE WHEN STV_TO_ELECTRIC THEN 1 END) as STOVE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN FIRE_TO_ELECTRIC THEN 1 END) as FIRE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN PELLET_TO_ELECTRIC THEN 1 END) as PELLET_TO_ELECTRIC_SUM
,COUNT(CASE WHEN MERIDIAN THEN 1 END) as WITHIN_MERIDIAN_SUM
,count(CASE WHEN hb357.stv_to_gas then 1 END) +
count(CASE WHEN hb357.fire_to_gas then 1 END) +
count(CASE WHEN hb357.pellet_to_gas then 1 END) +
count(CASE WHEN hb357.stv_to_electric then 1 END) +
count(CASE WHEN hb357.fire_to_electric then 1 END) +
count(CASE WHEN hb357.pellet_to_electric then 1 END) +
count(CASE WHEN hb357.meridian then 1 END ) AS county_totals
FROM woodburn.HB357
WHERE app_status IN ('pending','approved')
AND COUNTY IS NOT NULL
AND TRIM(COUNTY) != ''
GROUP BY rollup (county)
I have a table likse this:
my index is id_station_date_hour
My query:
select id_station,area_type,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_time,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_time_prev,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 180 and (zone1+zone2+zone3+cashiertime+special) < 360 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_3to6,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 180 and (zone1+zone2+zone3+cashiertime+special) < 360 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_3to6_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 360 and (zone1+zone2+zone3+cashiertime+special) < 600 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_6to10,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 360 and (zone1+zone2+zone3+cashiertime+special) < 600 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_6to10_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_less3,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_less3_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 60 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_1to3,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 60 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_1to3_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and (zone1+zone2+zone3+cashiertime+special) < 900 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_10to15,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and (zone1+zone2+zone3+cashiertime+special) < 900 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_10to15_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 60 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_less1,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 60 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_less1_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 900 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_over15,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 900 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_over15_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_over10,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_over10_prev,
sum(case when goinside = 1 and type = 1 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as man,
sum(case when goinside = 1 and type = 2 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as woman,
sum(case when goinside = 1 and type = 3 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as couple,
sum(case when goinside = 1 and type = 4 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as boy,
sum(case when goinside = 1 and type = 5 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as girl,
sum(case when goinside = 1 and type = 6 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as young_couple,
sum(case when goinside = 1 and type = 7 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as old_man,
sum(case when goinside = 1 and type = 8 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as old_woman,
sum(case when goinside = 1 and type = 9 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as old_couple,
sum(case when goinside = 1 and type = 10 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as family,
sum(case when goinside = 1 and type = 10 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then family_total else 0 end) as family_total,
sum(case when goinside = 1 and type = 11 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as group,
sum(case when goinside = 1 and type = 11 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then group_man else 0 end) as group_man,
sum(case when goinside = 1 and type = 11 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then group_woman else 0 end) as group_woman,
sum(case when goinside = 1 and type = 12 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as empty,
sum(case when goinside = 1 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as total_entries,
sum(case when goinside = 1 and type = 1 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as man_prev,
sum(case when goinside = 1 and type = 2 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as woman_prev,
sum(case when goinside = 1 and type = 3 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as couple_prev,
sum(case when goinside = 1 and type = 4 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as boy_prev,
sum(case when goinside = 1 and type = 5 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as girl_prev,
sum(case when goinside = 1 and type = 6 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as young_couple_prev,
sum(case when goinside = 1 and type = 7 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as old_man_prev,
sum(case when goinside = 1 and type = 8 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as old_woman_prev,
sum(case when goinside = 1 and type = 9 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as old_couple_prev,
sum(case when goinside = 1 and type = 10 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as family_prev,
sum(case when goinside = 1 and type = 10 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then family_total else 0 end) as family_total_prev,
sum(case when goinside = 1 and type = 11 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as grou_prev,
sum(case when goinside = 1 and type = 11 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then group_man else 0 end) as group_man_prev,
sum(case when goinside = 1 and type = 11 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then group_woman else 0 end) as group_woman_prev,
sum(case when goinside = 1 and type = 12 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as empty_prev,
sum(case when goinside = 1 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as total_entries_prev
from data_1034_detail where id_station IN (2399,2397) AND ((date >= '2017-10-01' and date <= '2017-10-31' AND hour >= 9 and hour < 22) OR (date >= '2017-08-31' and date <= '2017-09-30' AND hour >= 9 and hour < 22)) group by id_station, area_type
actually all fields selected area different condition, so it will make the query speed working slowly if I add more condition and selected fields. How can I set up proper index in this case?
Explain:
'HashAggregate (cost=304337.96..304338.36 rows=40 width=428) (actual time=7233.402..7233.449 rows=37 loops=1)'
' Group Key: id_station, area_type'
' -> Seq Scan on data_1034_detail (cost=0.00..17573.72 rows=218904 width=64) (actual time=0.035..394.334 rows=282899 loops=1)'
' Filter: ((id_station = ANY ('{2399,2397}'::bigint[])) AND (hour >= 9) AND (hour < 22) AND (((date >= '2017-10-01'::date) AND (date <= '2017-10-31'::date)) OR ((date >= '2017-08-31'::date) AND (date <= '2017-09-30'::date))))'
'Planning time: 0.735 ms'
'Execution time: 7234.169 ms'
And any chance to make this query execute in 1s?
It is the arithmetic that makes the query slow.
I am not sure, but maybe you can win some if you use a FILTER clause with the summation.
Instead of
sum(CASE WHEN goinside = 1
AND (zone1 + zone2 + zone3 + cashiertime + special) > 0
AND date >= '2017-10-01'
AND date <= '2017-10-31'
AND hour >= 9
AND hour < 22
THEN zone1 + zone2 + zone3 + cashiertime + special
ELSE 0
END) AS ex_z1z2z3z4z5_time
you could write:
sum(zone1 + zone2 + zone3 + cashiertime + special)
FILTER (WHERE goinside = 1
AND (zone1 + zone2 + zone3 + cashiertime + special) > 0
AND date >= '2017-10-01'
AND date <= '2017-10-31'
AND hour >= 9
AND hour < 22) AS ex_z1z2z3z4z5_time
You will still have to do all the calculations, but the sum will be over fewer items.
Perhaps PG-Strom can help you here – this extension delegates operations that can be parallelized to the GPU.
I want to return data from yesterday and 8 days ago.
To do this I use the following line in my query:
WHERE (o.status_date::date = now()::date - INTERVAL '8 days')
OR (o.status_date::date = now()::date - INTERVAL '1 day')
However, this returns a "Division by zero" error. When I use only one of the two, so for example:
WHERE (o.status_date::date = now()::date - INTERVAL '8 days')
I get no error...
I don't understand where the error comes from, or perhaps I'm making a very straightforward mistake. Any help is appreciated!
Edited, these are the calculations done in my query:
SUM(CASE WHEN o.status_id = '12' THEN 1 ELSE 0 END) AS failed_63,
SUM(CASE WHEN o.status_id IN ('6','11','12','14','22','24') THEN 1 ELSE 0 END) AS total_orders,
ROUND(
(SUM(CASE WHEN o.status_id = '12' THEN 1 ELSE 0 END) * 100)::numeric /
(SUM(CASE WHEN o.status_id IN ('11','12','14','22','24') THEN 1 ELSE 0 END)), 2) AS perc_fail,
COUNT(DISTINCT i.order_id) AS order_issues,
ROUND(
(COUNT(DISTINCT i.order_id) * 100)::numeric / (SUM(CASE WHEN o.status_id IN ('11','12','14','22','24') THEN 1 ELSE 0 END)), 2) AS issue_rate,
SUM(CASE WHEN o.status_id = '6' THEN 1 ELSE 0 END) AS overdue_53,
ROUND(
(SUM(CASE WHEN o.status_id = '6' THEN 1 ELSE 0 END) * 100)::numeric /
(SUM(CASE WHEN o.status_id IN ('6','11','12','14','22','24') THEN 1 ELSE 0 END)), 2) AS perc_overdue,
ROUND(
(AVG(dop.vendor_confirmation_time)::numeric / 60), 2) AS avg_v_confirmation_time,
CASE
WHEN (AVG(dop.vendor_confirmation_time)::numeric / 60) < 3 THEN 'good'
WHEN (AVG(dop.vendor_confirmation_time)::numeric / 60) IS NULL THEN 'n/a'
ELSE 'bad'
END AS vendor_response
You have several cases in your query where your divisor might be 0, as in:
SUM(CASE WHEN o.status_id IN ('6','11','12','14','22','24') THEN 1 ELSE 0 END)
The best way to solve this is to use a sub-query to calculate all the sums, which are repeated anyway, and then do the division and rounding in the main query, where the divisor is not 0:
SELECT
sum12 AS failed_63,
sum6 + sum12 + sum11_24 AS total_orders,
CASE WHEN sum12 + summ11_24 > 0 THEN round(sum12 * 100. / (sum11_24 + sum 12), 2)
ELSE NULL END AS perc_fail,
order_issues,
CASE WHEN sum12 + summ11_24 > 0 THEN round(order_issues * 100. / (sum12 + sum11_24), 2)
ELSE NULL END AS issue_rate,
sum6 AS overdue_53,
CASE WHEN sum6 + sum12 + sum11_24 > 0 THEN round(sum6 / (sum6 + sum12 + sum11_24), 2)
ELSE NULL END AS perc_overdue,
round(avg_v_confirmation_time, 2) AS avg_v_confirmation_time,
CASE
WHEN (avg_v_confirmation_time) < 3 THEN 'good'
WHEN (avg_v_confirmation_time) IS NULL THEN 'n/a'
ELSE 'bad'
END AS vendor_response
FROM (
SELECT
sum(CASE WHEN o.status_id = '6' THEN 1 ELSE 0 END) AS sum6,
sum(CASE WHEN o.status_id = '12' THEN 1 ELSE 0 END) AS sum12,
sum(CASE WHEN o.status_id IN ('11','14','22','24') THEN 1 ELSE 0 END) AS sum11_24,
count(DISTINCT i.order_id) AS order_issues,
avg(dop.vendor_confirmation_time::numeric / 60) AS avg_v_confirmation_time
FROM o, i, dop
WHERE ... ) sub
In this case I set all columns where the divisor would be 0 to NULL; change as appropriate.
For future questions:
List your PostgreSQL version
Post the entire query with table qualifiers for all columns
Preferably, post the table structure
I still don't know why my first line didn't work, but I've now found a work-around by using the following:
WHERE o.status_date::date BETWEEN CURRENT_DATE - INTERVAL '8 days' AND CURRENT_DATE - INTERVAL '1 day'
AND o.status_date::date NOT BETWEEN CURRENT_DATE - INTERVAL '7 days' AND CURRENT_DATE - INTERVAL '2 days'
I have table called RUGS with the data below. How do I write a TSQl query to get the data as shown in Output. I am not familiar with unPIVOT
`cono ARtype days Revenue PPD
140 MCD 5 1000 500
140 MRA 6 2000 600
140 MRA 7 3000 700
141 MCD 1 5000 100
141 MRA 2 6000 200
141 MRA 3 7000 300`
Result
140 MCD 5 1000 500 MRA 6 2000 600 MRA 7 3000 700
141 MCD 1 5000 100 MRA 2 6000 200 MRA 3 7000 300
Given that every cono will have exactly 3 records (as stated in the comments), a cte with row_number can be used with case statements.
If any have less than three records, you will see blanks and zeroes in the results. Any with more than three will not have all records represented.
Here is an example with #RUGS as a table variable:
declare #RUGS table (cono int, ARType char(3), [days] int, Revenue int, PPD int)
insert into #RUGS VALUES
(140,'MCD',5,1000,500)
,(140,'MRA',6,2000,600)
,(140,'MRA',7,3000,700)
,(141,'MCD',1,5000,100)
,(141,'MRA',2,6000,200)
,(141,'MRA',3,7000,300);
with cte as
(
select row_number() over(partition by cono order by (select 1)) as rn, * from #RUGS
)
select cono,
max(case when rn = 1 then ARType else '' end) as ARType1,
max(case when rn = 1 then days else '' end) as days1,
max(case when rn = 1 then Revenue else '' end) as Revenue1,
max(case when rn = 1 then PPD else '' end) as PPD1,
max(case when rn = 2 then ARType else '' end) as ARType2,
max(case when rn = 2 then days else '' end) as days2,
max(case when rn = 2 then Revenue else '' end) as Revenue2,
max(case when rn = 2 then PPD else '' end) as PPD2,
max(case when rn = 3 then ARType else '' end) as ARType3,
max(case when rn = 3 then days else '' end) as days3,
max(case when rn = 3 then Revenue else '' end) as Revenue3,
max(case when rn = 3 then PPD else '' end) as PPD3
from cte group by cono
When unfiltered, dense_rank on FeedDeliveryNutrients.NutrientID over 150,000 rows is 3.5x faster than joining to Nutrients with row_number on Nutrients.ID and using the joined row number. When filtered to a specific flock, joining with row_number is 9x faster.
Is there any optimization technique that could get the best of both worlds in a single query?
Fastest when unfiltered (150,000 rows returned):
select
FeedDeliveries.FlockID,
FeedDeliveryID,
DeliveryLb,
Bin,
DeliveryDate,
FormulaID,
FeedEnergy,
Nutrient1, Nutrient2, Nutrient3, Nutrient4, Nutrient5, Nutrient6, Nutrient7, Nutrient8, Nutrient9, Nutrient10, Nutrient11, Nutrient12, Nutrient13, Nutrient14, Nutrient15
from (
select
FeedDeliveryID,
sum(case when dense_rank = 1 then Amount end) as Nutrient1,
sum(case when dense_rank = 2 then Amount end) as Nutrient2,
sum(case when dense_rank = 3 then Amount end) as Nutrient3,
sum(case when dense_rank = 4 then Amount end) as Nutrient4,
sum(case when dense_rank = 5 then Amount end) as Nutrient5,
sum(case when dense_rank = 6 then Amount end) as Nutrient6,
sum(case when dense_rank = 7 then Amount end) as Nutrient7,
sum(case when dense_rank = 8 then Amount end) as Nutrient8,
sum(case when dense_rank = 9 then Amount end) as Nutrient9,
sum(case when dense_rank = 10 then Amount end) as Nutrient10,
sum(case when dense_rank = 11 then Amount end) as Nutrient11,
sum(case when dense_rank = 12 then Amount end) as Nutrient12,
sum(case when dense_rank = 13 then Amount end) as Nutrient13,
sum(case when dense_rank = 14 then Amount end) as Nutrient14,
sum(case when dense_rank = 15 then Amount end) as Nutrient15
from (select *, dense_rank() over (partition by FeedDeliveryID order by NutrientID) as dense_rank from dbo.FeedDeliveryNutrients) n
group by FeedDeliveryID
) pvt
join dbo.FeedDeliveries on FeedDeliveries.ID = FeedDeliveryID
Fastest when filtered by dbo.FeedDeliveries.FlockID (~100 rows returned):
select
FeedDeliveries.FlockID,
FeedDeliveryID,
DeliveryLb,
Bin,
DeliveryDate,
FormulaID,
FeedEnergy,
Nutrient1, Nutrient2, Nutrient3, Nutrient4, Nutrient5, Nutrient6, Nutrient7, Nutrient8, Nutrient9, Nutrient10, Nutrient11, Nutrient12, Nutrient13, Nutrient14, Nutrient15
from (
select
FeedDeliveryID,
sum(case when n.row_number = 1 then Amount end) as Nutrient1,
sum(case when n.row_number = 2 then Amount end) as Nutrient2,
sum(case when n.row_number = 3 then Amount end) as Nutrient3,
sum(case when n.row_number = 4 then Amount end) as Nutrient4,
sum(case when n.row_number = 5 then Amount end) as Nutrient5,
sum(case when n.row_number = 6 then Amount end) as Nutrient6,
sum(case when n.row_number = 7 then Amount end) as Nutrient7,
sum(case when n.row_number = 8 then Amount end) as Nutrient8,
sum(case when n.row_number = 9 then Amount end) as Nutrient9,
sum(case when n.row_number = 10 then Amount end) as Nutrient10,
sum(case when n.row_number = 11 then Amount end) as Nutrient11,
sum(case when n.row_number = 12 then Amount end) as Nutrient12,
sum(case when n.row_number = 13 then Amount end) as Nutrient13,
sum(case when n.row_number = 14 then Amount end) as Nutrient14,
sum(case when n.row_number = 15 then Amount end) as Nutrient15
from dbo.FeedDeliveryNutrients
join (select *, row_number() over (order by ID) as row_number from dbo.Nutrients) n on n.ID = NutrientID
group by FeedDeliveryID
) pvt
join dbo.FeedDeliveries on FeedDeliveries.ID = FeedDeliveryID
You already got the answer. Optimize for the most critical scenario.
From start I can use optimize for the 150.000 rows scenario but you must sniff a bit on your actual production server. If that 150.000 only happens a few times /week and the 100 rows ill hit your server many times/minute that is the more critical for you.