I have an sql query that basically queries a table containing two columns: event_name and event_count.
event_count is an integer representing seconds the event took to execute. I wrote the query below that rolls up events into tiers, ie 1-5 seconds, 5-10 seconds, etc so we can determine how long each takes to execute.
I'm wondering if there is a better approach to do what I'm doing below as I don't think this is currently very optimal since it has to run sum() on every case.
I tried to put the previously selected column (d_event_count) in the case statement like this:
(CASE WHEN d_event_count >= 0 and d_event_count < 5 THEN d_event_count ELSE 0 END) as d_time_1_5,
but it fails indicating column does not exist in the table so I'm here looking for some help :)
select
event_name as d_event_name,
sum(event_count) as d_event_count,
(CASE WHEN sum(event_count) >= 0 and sum(event_count) < 5 THEN sum(event_count) ELSE 0 END) as d_time_1_5,
(CASE WHEN sum(event_count) >= 5 and sum(event_count) < 10 THEN sum(event_count) ELSE 0 END) as d_time_5_10,
(CASE WHEN sum(event_count) >= 10 and sum(event_count) < 15 THEN sum(event_count) ELSE 0 END) as d_time_10_15,
(CASE WHEN sum(event_count) >= 15 and sum(event_count) < 30 THEN sum(event_count) ELSE 0 END) as d_time_15_30,
(CASE WHEN sum(event_count) >= 30 and sum(event_count) < 45 THEN sum(event_count) ELSE 0 END) as d_time_30_45,
(CASE WHEN sum(event_count) >= 45 and sum(event_count) < 60 THEN sum(event_count) ELSE 0 END) as d_time_45_60,
(CASE WHEN sum(event_count) >= 60 and sum(event_count) < 120 THEN sum(event_count) ELSE 0 END) as d_time_60_120,
(CASE WHEN sum(event_count) >= 120 and sum(event_count) < 180 THEN sum(event_count) ELSE 0 END) as d_time_120_180,
(CASE WHEN sum(event_count) >= 180 and sum(event_count) < 240 THEN sum(event_count) ELSE 0 END) as d_time_180_240,
(CASE WHEN sum(event_count) >= 240 and sum(event_count) < 300 THEN sum(event_count) ELSE 0 END) as d_time_240_300,
(CASE WHEN sum(event_count) >= 300 THEN sum(event_count) ELSE 0 END) as d_time_300
from
product_events
where
...
group by 1
Changing the table structure is not a possibility, there are dozens of other columns, this is just a stripped down representation.
Can someone help me out?
Try in this way, it uses a cumulative sum of d_event_count:
create temp table ev as
select *
from (
values
('event 1'::text, 5::int),
('event 2'::text, 5::int),
('event 3'::text, 5::int),
('event 4'::text, 5::int),
('event 5'::text, 5::int),
('event 6'::text, 5::int),
('event 7'::text, 5::int),
('event 8'::text, 5::int),
('event 9'::text, 5::int)
) t (event_name, d_event_count);
with sm as
(
select event_name, sum(d_event_count) over (order by event_name) as total
from ev
)
select event_name, total,
case when total between 0 and 5 then 'd_time_1_5'
when total between 6 and 10 then 'd_time_6_10'
when total between 11 and 15 then 'd_time_11_15'
else 'more than 15'
end as d_name
from sm;
+------------+-------+--------------+
| event_name | total | d_name |
+------------+-------+--------------+
| event 1 | 5 | d_time_1_5 |
+------------+-------+--------------+
| event 2 | 10 | d_time_6_10 |
+------------+-------+--------------+
| event 3 | 15 | d_time_11_15 |
+------------+-------+--------------+
| event 4 | 20 | more than 15 |
+------------+-------+--------------+
| event 5 | 25 | more than 15 |
+------------+-------+--------------+
| event 6 | 30 | more than 15 |
+------------+-------+--------------+
| event 7 | 35 | more than 15 |
+------------+-------+--------------+
| event 8 | 40 | more than 15 |
+------------+-------+--------------+
| event 9 | 45 | more than 15 |
+------------+-------+--------------+
Or another solution using a WINDOW function:
select event_name, sum(d_event_count) over w1 as total,
case when sum(d_event_count) over w1 between 0 and 5 then 'd_time_1_5'
when sum(d_event_count) over w1 between 6 and 10 then 'd_time_6_10'
when sum(d_event_count) over w1 between 11 and 15 then 'd_time_11_15'
else 'more than 15'
end as d_name
from ev
WINDOW w1 AS (order by event_name);
Check it here: http://rextester.com/BTR25807
Related
I'm trying to create an indicator for value increase over time within a group. In particular, I'm trying to flag certain grp if value ever increases by 50% over time.
I have a raw data that looks like:
id grp value_dt value
--------------------------------
1 1 11/20/20 1.4
1 1 11/21/20 0.8
1 1 11/24/20 2.8
1 1 11/25/20 2.5
1 2 11/29/20 1.5
1 2 12/1/20 1.6
2 1 11/21/20 0.8
2 2 11/26/20 0.9
2 3 12/1/20 0.9
2 3 12/3/20 2.8
You can see that for id = 1 and grp = 1, the value fluctuates as it increases and decreases over time, but because it had increase over time between 11/21/20 and 11/24/20 from 0.8 to 2.8 (greater than 50% increase), I want to flag the whole grp 1. I want my output to look like:
id grp val_ind
-----------------------
1 1 1
1 2 0
2 1 0
2 2 0
2 3 1
I can only think of using min and max (something like below), which doesn't include the 'over the time' factor in...
select id,
grp,
min(value) as min_grp,
max(value) as max_grp,
(max_grp - min_grp) as val_diff,
case when val_diff >= min_grp * 1.5 then 1 else 0 end as val_ind
If anyone can offer their advice, I will greatly appreciate it!
I think you want to know if at any point at time there is an increase of 50% , you flag that group. if yes , here is how you can do it,
you need to use cte and window functions :
; WITH cte AS (
SELECT *
, CASE WHEN COALESCE(LEAD(value) OVER (PARTITION BY id, grp ORDER BY value_dt),0) >= value* 2 THEN 1 ELSE 0 END val_ind
FROM ttt
)
SELECT
id , grp , MAX(val_ind) val_ind
FROM cte
GROUP BY
id , grp
id | grp | val_ind
-: | --: | ------:
1 | 1 | 1
1 | 2 | 0
2 | 1 | 0
2 | 2 | 0
2 | 3 | 1
db<>fiddle here
I am using this CASE statement to show a total count of visits and average length of visit grouped by age groups:
CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 then (
Count(VisitID),
AVG(DATEDIFF(dd,StartDate,EndDate ))
)
WHEN AgeCalcSort >= 2 AND AgeCalcSort <= 17 then (
Count(VisitID),
AVG(DATEDIFF(dd,StartDate,EndDate ))
)
WHEN AgeCalcSort >= 18 AND AgeCalcSort <= 64 then (
Count(VisitID),
AVG(DATEDIFF(dd,StartDate,EndDate ))
)
WHEN AgeCalcSort >= 65 then (
Count(VisitID),
AVG(DATEDIFF(dd,StartDate,EndDate ))
)
END,
The result should look like this:
Age 1 Count Age 1 Avg LOS Age 2 Count Age 1 Avg LOS Age 3 Count Age 3 Avg LOS Age 4 Count Age 4 Avg LOS
5 5.3 18 9.2 20 12 0 0
Can anyone adivse what am I doing wrong, or a better way to achieve the end result? Thanks In advance.
You have mentioned 2 points:
1) Can anyone adivse what am I doing wrong
You are using the CASE expression in your query incorrectly.
You cannot have 2 columns returned when some condition is satisfied in CASE statement.
As per Microsoft documentation, CASE evaluates a list of conditions and returns one of multiple possible result expressions.
Check this Microsoft white paper for further study Ref. URL
2) a better way to achieve the end result
There can be many ways to achieve this.
Below is one of the simple way. try the query below:
SELECT
SUM(CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 THEN 1 ELSE 0 END) [Age 1 Count],
AVG(CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 1 Avg LOS]
SUM(CASE WHEN AgeCalcSort = 2 AND AgeCalcSort <= 17 THEN 1 ELSE 0 END) [Age 2 Count],
AVG(CASE WHEN AgeCalcSort = 2 AND AgeCalcSort <= 17 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 2 Avg LOS]
SUM(CASE WHEN AgeCalcSort = 18 AND AgeCalcSort <= 64 THEN 1 ELSE 0 END) [Age 3 Count],
AVG(CASE WHEN AgeCalcSort = 18 AND AgeCalcSort <= 64 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 3 Avg LOS]
SUM(CASE WHEN AgeCalcSort >= 65 THEN 1 ELSE 0 END) [Age 4 Count],
AVG(CASE WHEN AgeCalcSort >= 65 THEN DATEDIFF(DAY,StartDate,EndDate) ELSE NULL END) [Age 4 Avg LOS]
FROM [YourTableName]
Query explanation
I have achieved count by using SUM, if you look into any of count logic you will notice it says when it satisfies condition 1 else 0. and that is summed later using SUM. So that all 1's ultimately gives count.
for average you will notice that then condition is not satisfied I am using NULL, which is intentional, to avoid wrong math.
for in TSQL query AVG of (2,4,NULL) is 3, while AVG of (2,4,0) is 2. so in your case NULL will help to avoid messing average value.
A case expression returns a single value, which you may then count or average.
It is not possible to produce multiple columns of output from a singe case expression. So, you need one case expression for each wanted column of output, like this:
select
COUNT(CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 then VisitID end)
, AVG(CASE WHEN AgeCalcSort = 0 AND AgeCalcSort <= 1 then DATEDIFF(dd,StartDate,EndDate ) end)
, COUNT(CASE WHEN AgeCalcSort = 2 AND AgeCalcSort <= 17 then VisitID end)
, AVG(CASE WHEN AgeCalcSort = 2 AND AgeCalcSort <= 17 then DATEDIFF(dd,StartDate,EndDate ) end)
, COUNT(CASE WHEN AgeCalcSort = 18 AND AgeCalcSort <= 64 then VisitID end)
, AVG(CASE WHEN AgeCalcSort = 18 AND AgeCalcSort <= 64 then DATEDIFF(dd,StartDate,EndDate ) end)
, COUNT(CASE WHEN AgeCalcSort = 65 then VisitID end)
, AVG(CASE WHEN AgeCalcSort = 65 then DATEDIFF(dd,StartDate,EndDate ) end)
from ...
Notes:
place each case expression inside the relevant aggregate function
the count() function ignores NULLs so if the when conditions are not met the count will not increment
whilst T-SQL documentation can sometimes use the term "case statement" technically that is incorrect; e.g. a complete select query is a "statement", and "expressions" evaluate to single values, hence the correct term is case expression
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 have a query that count the total number of users registered in our service per day, per hour. My problem is that i want to appear the hour in range style. You can see below:
Query:
SELECT
case
when extract(dow from us.created::timestamp) = 0 then 'Sunday'
when extract(dow from us.created::timestamp) = 1 then 'Monday'
when extract(dow from us.created::timestamp) = 2 then 'Tuesday'
when extract(dow from us.created::timestamp) = 3 then 'Wednesday'
when extract(dow from us.created::timestamp) = 4 then 'Thursday'
when extract(dow from us.created::timestamp) = 5 then 'Friday'
when extract(dow from us.created::timestamp) = 6 then 'Saturday'
end as wday,
extract(hour from us.created::timestamp) as whour,
count(us.id)
FROM users us
GROUP BY wday,whour order by wday, whour
Query Result:
wday whour count
Friday 0 364
Friday 1 156
Friday 2 79
Friday 3 39
Friday 4 55
Friday 5 32 ....
I want to count and appear the results in this format:
wday whour count
Friday 0-1 364
Friday 1-2 156
Friday 2-3 79
Friday 3-4 39
Friday 4-5 55
Friday 5-6 32 ....
How can i do this?
try smth like :
WITH a as (
SELECT
to_char(us.created::timestamp,'Day') as wday,
extract(hour from us.created::timestamp) as whour,
count(us.id)
FROM users us
GROUP BY wday,whour
)
select
wday
, coalesce(whour,'-',lead(whour) over (partition by wday order by whour)) whour
, count
from a
order by wday, whour
here's the logic sample:
t=# with v(i,e) as (
values
('Friday',2),('Friday',3),('Saturday',4),('Saturday',5),('Saturday',6),('Friday',4),('Friday',5),('Friday',0),('Friday',1)
)
select i,e,concat(e,'-',lead(e) over (partition by i order by e))
from v;
i | e | concat
----------+---+--------
Friday | 0 | 0-1
Friday | 1 | 1-2
Friday | 2 | 2-3
Friday | 3 | 3-4
Friday | 4 | 4-5
Friday | 5 | 5-
Saturday | 4 | 4-5
Saturday | 5 | 5-6
Saturday | 6 | 6-
(9 rows)
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)