SQL - % Breakout by Hour - sql

I'm trying to write a query that will break out what percentage of time is utilized within a hour given a time range.
Sample data:
declare #date table(id int, Start_time time, End_time time)
Insert Into #date(id, Start_time, End_time) values
(0, '09:15', '17:15')
, (1, '10:45', '16:30')
, (2, '08:05', '17:45')
, (3, '07:00', '15:00')
, (4, '07:30', '8:30')
Looking to get output like this:
Any help would greatly be appreciated.

By using an ad-hoc tally table to create every minute of the day. This assumes you are processing to the minute. Then it becomes a small matter of the conditional aggregation.
Example
;with cte as (
Select A.ID
,Hrs = datepart(hour,T)
,Cnt = convert(decimal(10,2),sum(1.0) / 60)
From #date A
Join (
Select Top (1440) T=dateadd(MINUTE,-1+Row_Number() Over (Order By (Select NULL)),0) From master..spt_values n1,master..spt_values n2
) B on T >=convert(datetime,Start_Time) and t<convert(datetime,End_Time)
Group By A.ID,datepart(hour,T)
)
Select ID
,h3 = sum(case when Hrs=3 then Cnt else 0 end)
,h4 = sum(case when Hrs=4 then Cnt else 0 end)
,h5 = sum(case when Hrs=5 then Cnt else 0 end)
,h6 = sum(case when Hrs=6 then Cnt else 0 end)
,h7 = sum(case when Hrs=7 then Cnt else 0 end)
,h8 = sum(case when Hrs=8 then Cnt else 0 end)
,h9 = sum(case when Hrs=9 then Cnt else 0 end)
,h10 = sum(case when Hrs=10 then Cnt else 0 end)
,h11 = sum(case when Hrs=11 then Cnt else 0 end)
,h12 = sum(case when Hrs=12 then Cnt else 0 end)
,h13 = sum(case when Hrs=13 then Cnt else 0 end)
,h14 = sum(case when Hrs=14 then Cnt else 0 end)
,h15 = sum(case when Hrs=15 then Cnt else 0 end)
,h16 = sum(case when Hrs=16 then Cnt else 0 end)
,h17 = sum(case when Hrs=17 then Cnt else 0 end)
,h18 = sum(case when Hrs=18 then Cnt else 0 end)
From cte
Group By ID
Returns

Related

Counting columns with a where clause

Is there a way to count a number of columns which has a particular value for each rows in Hive.
I have data which looks like in input and I want to count how many columns have value 'a' and how many column have value 'b' and get the output like in 'Output'.
Is there a way to accomplish this with Hive query?
One method in Hive is:
select ( (case when cl_1 = 'a' then 1 else 0 end) +
(case when cl_2 = 'a' then 1 else 0 end) +
(case when cl_3 = 'a' then 1 else 0 end) +
(case when cl_4 = 'a' then 1 else 0 end) +
(case when cl_5 = 'a' then 1 else 0 end)
) as count_a,
( (case when cl_1 = 'b' then 1 else 0 end) +
(case when cl_2 = 'b' then 1 else 0 end) +
(case when cl_3 = 'b' then 1 else 0 end) +
(case when cl_4 = 'b' then 1 else 0 end) +
(case when cl_5 = 'b' then 1 else 0 end)
) as count_b
from t;
To get the total count, I would suggest using a subquery and adding count_a and count_b.
Use lateral view with explode on the data and do the aggregations on it.
select id
,sum(cast(col='a' as int)) as cnt_a
,sum(cast(col='b' as int)) as cnt_b
,sum(cast(col in ('a','b') as int)) as cnt_total
from tbl
lateral view explode(array(ci_1,ci_2,ci_3,ci_4,ci_5)) tbl as col
group by id

Inner case statement is throwing an error when trying to sum the values

select sum(t.amount)
from
(select yearquarter,
(case when sum(case when type not in (3, 4) then 1 else 0 end) = 0
then sum(amount)
else sum(case when type not in (3, 4) then amount else 0 end)
end)
from t
where status = 'A'
group by yearquarter)t;
Need to sum up "Amount" from inner case statement but Getting an error
You didn't name the amount column in your t subquery.
select sum(t.amount)
from
(select yearquarter,
(case when sum(case when type not in (3, 4) then 1 else 0 end) = 0
then sum(amount)
else sum(case when type not in (3, 4) then amount else 0 end)
end) AS amount
from t
where status = 'A'
group by yearquarter)t;

Full outer join with "case when" and subquery

I have a full outer join query with case when and sub query in oracle. What I am trying to accomplish is aggregating current year data and previous year data from the same table in order to compare them. However my FULL OUTER JOIN is acting as an inner join not returning the null values from both the current year and the previous year.
Here is my code:
SELECT
SQ1.CHANNEL,
SQ1.SHORT,
SQ1.NAME,
SQ1.RDC,
SQ1.CY_APPROVED_COUNT,
SQ2.PY_APPROVED_COUNT,
SQ1.CY_APPROVED_VOLUME,
SQ2.PY_APPROVED_VOLUME,
SQ1.CY_DECLINED_COUNT,
SQ2.PY_DECLINED_COUNT,
SQ1.CY_DECLINED_VOLUME,
SQ2.PY_DECLINED_VOLUME,
SQ1.CY_RETURNED_COUNT,
SQ2.PY_RETURNED_COUNT,
SQ1.CY_RETURNED_VOLUME,
SQ2.PY_RETURNED_VOLUME
FROM ( SELECT
CHANNEL,
SHORT,
NAME,
RDC,
SUM (CASE WHEN STATUS = 'Approved' THEN APP_COUNTS ELSE 0 END) AS CY_APPROVED_COUNT,
SUM (CASE WHEN STATUS = 'Approved' THEN PROJ_VOL ELSE 0 END) AS CY_APPROVED_VOLUME,
SUM (CASE WHEN STATUS = 'Declined' THEN APP_COUNTS ELSE 0 END) AS CY_DECLINED_COUNT,
SUM (CASE WHEN STATUS = 'Declined' THEN PROJ_VOL ELSE 0 END) AS CY_DECLINED_VOLUME,
SUM (CASE WHEN STATUS = 'Returned' THEN APP_COUNTS ELSE 0 END) AS CY_RETURNED_COUNT,
SUM (CASE WHEN STATUS = 'Returned' THEN PROJ_VOL ELSE 0 END) AS CY_RETURNED_VOLUME
FROM WFRT_MSP_SP_MTD
WHERE PERIOD >= TO_DATE('2016/02/01', 'yyyy/mm/dd')
AND PERIOD <= TO_DATE('2016/02/13','yyyy/mm/dd')
AND CHANNEL = 'MSP'
AND RDC = 'BASE'
GROUP BY
CHANNEL,
SHORT,
NAME,
RDC
) SQ1
-- NOT CORRECTLY SHOWING NULL VALUES
FULL OUTER JOIN
( SELECT
CHANNEL,
SHORT,
NAME,
RDC,
SUM (CASE WHEN STATUS = 'Approved' THEN APP_COUNTS ELSE 0 END) AS PY_APPROVED_COUNT,
SUM (CASE WHEN STATUS = 'Approved' THEN PROJ_VOL ELSE 0 END) AS PY_APPROVED_VOLUME,
SUM (CASE WHEN STATUS = 'Declined' THEN APP_COUNTS ELSE 0 END) AS PY_DECLINED_COUNT,
SUM (CASE WHEN STATUS = 'Declined' THEN PROJ_VOL ELSE 0 END) AS PY_DECLINED_VOLUME,
SUM (CASE WHEN STATUS = 'Returned' THEN APP_COUNTS ELSE 0 END) AS PY_RETURNED_COUNT,
SUM (CASE WHEN STATUS = 'Returned' THEN PROJ_VOL ELSE 0 END) AS PY_RETURNED_VOLUME
FROM WFRT_MSP_SP_MTD
WHERE PERIOD >= TO_DATE('2015/02/01', 'yyyy/mm/dd')
AND PERIOD <= TO_DATE('2015/02/13','yyyy/mm/dd')
AND CHANNEL = 'MSP'
AND RDC = 'BASE'
GROUP BY
CHANNEL,
SHORT,
NAME,
RDC
) SQ2
ON sq1.short = sq2.short
;
Please help if you can.
Just use conditional aggregation:
SELECT CHANNEL, SHORT, NAME, RDC,
SUM(CASE WHEN this_year = 1 AND STATUS = 'Approved' THEN APP_COUNTS ELSE 0 END) AS CY_APPROVED_COUNT,
SUM(CASE WHEN this_year = 1 AND STATUS = 'Approved' THEN PROJ_VOL ELSE 0 END) AS cY_APPROVED_VOLUME,
SUM(CASE WHEN this_year = 1 AND STATUS = 'Declined' THEN APP_COUNTS ELSE 0 END) AS CY_DECLINED_COUNT,
SUM(CASE WHEN this_year = 1 AND STATUS = 'Declined' THEN PROJ_VOL ELSE 0 END) AS CY_DECLINED_VOLUME,
SUM(CASE WHEN this_year = 1 AND STATUS = 'Returned' THEN APP_COUNTS ELSE 0 END) AS CY_RETURNED_COUNT,
SUM(CASE WHEN this_year = 1 AND STATUS = 'Returned' THEN PROJ_VOL ELSE 0 END) AS CY_RETURNED_VOLUME,
SUM(CASE WHEN prev_year = 1 AND STATUS = 'Approved' THEN APP_COUNTS ELSE 0 END) AS PY_APPROVED_COUNT,
SUM(CASE WHEN prev_year = 1 AND STATUS = 'Approved' THEN PROJ_VOL ELSE 0 END) AS PY_APPROVED_VOLUME,
SUM(CASE WHEN prev_year = 1 AND STATUS = 'Declined' THEN APP_COUNTS ELSE 0 END) AS PY_DECLINED_COUNT,
SUM(CASE WHEN prev_year = 1 AND STATUS = 'Declined' THEN PROJ_VOL ELSE 0 END) AS PY_DECLINED_VOLUME,
SUM(CASE WHEN prev_year = 1 AND STATUS = 'Returned' THEN APP_COUNTS ELSE 0 END) AS PY_RETURNED_COUNT,
SUM(CASE WHEN prev_year = 1 AND STATUS = 'Returned' THEN PROJ_VOL ELSE 0 END) AS PY_RETURNED_VOLUME
FROM (SELECT msm.*,
(CASE WHEN PERIOD >= DATE '2015-02-01' AND
PERIOD <= '2015-02-13'
THEN 1 ELSE 0
END) as prev_year,
(CASE WHEN PERIOD >= DATE '2016-02-01' AND
PERIOD <= '2016-02-13'
THEN 1 ELSE 0
END) as this_year
FROM WFRT_MSP_SP_MTD msm
) msm
WHERE CHANNEL = 'MSP' AND RDC = 'BASE'
GROUP BY CHANNEL, SHORT, NAME, RDC;

How to use having condition in SQL query

SELECT
userid,
CASE
WHEN (COUNT(CASE
WHEN onlinesportsgamewagers != 0
THEN 1
ELSE null
END)
+ COUNT(CASE
WHEN depositmade_amt != 0
THEN 1
ELSE null
END)) >= 10
THEN "VIP"
ELSE "NON-VIP"
END as VIPcheck
FROM
player_activity
WHERE
userid = 2023410
GROUP BY
year(txndate), month(txndate)
This query determines the user's VIP status for each month.
Ultimately, I want to have a query that determines if the user achieved VIP status for at least 3 months (including the current month). For the time being, it's only user 2023410, but eventually I want to run this for the whole database.
Therefore my ultimate output would be:
User - VIPcheck (3 different months w/ active status)
(one row per userID)
HAVING COUNT(CASE WHEN (COUNT(CASE WHEN onlinesportsgamewagers != 0
THEN 1
ELSE null
END)
+ COUNT(CASE WHEN depositmade_amt != 0
THEN 1
ELSE null
END)) >= 10
THEN 1
ELSE 0
END)
Tried the above having statement, but it didn't work. Any suggestions?
If I understand correctly, this gets the VIP status for one user by month:
SELECT userid, year(txndate), month(txndate),
(CASE WHEN SUM(CASE WHEN onlinesportsgamewagers <> 0 THEN 1 ELSE 0 END) +
SUM(CASE WHEN depositmade_amt <> 0 THEN 1 ELSE 0 END) >= 10
THEN 'VIP'
ELSE 'NON-VIP'
END) as VIPcheck
FROM player_activity
GROUP BY userid, year(txndate), month(txndate);
Another aggregation will get what you want:
SELECT userid,
(CASE WHEN SUM(VIPcheck = 'VIP') >= 3 THEN 'SUPER-VIP'
WHEN SUM(VIPcheck = 'VIP') >= 1 THEN 'VIP'
ELSE 'HOI POLLOI'
END) as status
FROM (SELECT userid, year(txndate), month(txndate),
(CASE WHEN SUM(CASE WHEN onlinesportsgamewagers <> 0 THEN 1 ELSE 0 END) +
SUM(CASE WHEN depositmade_amt <> 0 THEN 1 ELSE 0 END) >= 10
THEN 'VIP'
ELSE 'NON-VIP'
END) as VIPcheck
FROM player_activity
GROUP BY userid, year(txndate), month(txndate)
) uym
GROUP BY userid;

Sum data for many different results for same field

I am trying to find a better way to write this sql server code 2008. It works and data is accurate. Reason i ask is that i will be asked to do this for several other reports going forward and want to reduce the amount of code to upkeep going forward.
How can i take a field where i sum for the yes/no/- (dash) in each field without doing an individual sum as i have in code. Each table is a month of detail data which i sum using in a CTE. i changed the table name for each month and Union All to put data together. Is there a better way to do this. This is a small sample of code. Thanks for the help.
WITH H AS (
SELECT 'August' AS Month_Name
, SUM(CASE WHEN G.FFS = '-' THEN 1 ELSE 0 END) AS FFS_Dash
, SUM(CASE WHEN G.FFS = 'Yes' THEN 1 ELSE 0 END) AS FFS_Yes
, SUM(CASE WHEN G.FFS = 'No' THEN 1 ELSE 0 END) AS FFS_No
, SUM(CASE WHEN G.DNA = '-' THEN 1 ELSE 0 END) AS DNA_Dash
, SUM(CASE WHEN G.DNA = 'Yes' THEN 1 ELSE 0 END) AS DNA_Yes
, SUM(CASE WHEN G.DNA = 'No' THEN 1 ELSE 0 END) AS DNA_No
FROM table08 G )
, G AS (
SELECT 'July' AS Month_Name
, SUM(CASE WHEN G.FFS = '-' THEN 1 ELSE 0 END) AS FFS_Dash
, SUM(CASE WHEN G.FFS = 'Yes' THEN 1 ELSE 0 END) AS FFS_Yes
, SUM(CASE WHEN G.FFS = 'No' THEN 1 ELSE 0 END) AS FFS_No
, SUM(CASE WHEN G.DNA = '-' THEN 1 ELSE 0 END) AS DNA_Dash
, SUM(CASE WHEN G.DNA = 'Yes' THEN 1 ELSE 0 END) AS DNA_Yes
, SUM(CASE WHEN G.DNA = 'No' THEN 1 ELSE 0 END) AS DNA_No
FROM table07 G )
select * from H
UNION ALL
select * from G
How about:
SELECT Month_Name,
SUM(CASE WHEN G.FFS = '-' THEN 1 ELSE 0 END) AS FFS_Dash,
SUM(CASE WHEN G.FFS = 'Yes' THEN 1 ELSE 0 END) AS FFS_Yes,
SUM(CASE WHEN G.FFS = 'No' THEN 1 ELSE 0 END) AS FFS_No,
SUM(CASE WHEN G.DNA = '-' THEN 1 ELSE 0 END) AS DNA_Dash,
SUM(CASE WHEN G.DNA = 'Yes' THEN 1 ELSE 0 END) AS DNA_Yes,
SUM(CASE WHEN G.DNA = 'No' THEN 1 ELSE 0 END) AS DNA_No
FROM ((select 'July' as Month_Name, G.*
from table07 G
) union all
(select 'August', H.*
from table08 H
)
) gh
GROUP BY Month_Name;
However, having tables with the same structure is usually a sign of poor database design. You should have a single table with a column representing the month.