iterate SQL query to 30 days timeframe and count - sql

Currently, I have created a count based on a condition and populated 24 hours, 7 days and 30 days data by doing something like this, At the end I would like to create a time series to see how the number changes from day 1 till day 30
This is the code I am currently using
select
title,
item_name,
category,
sum(case when (first_seen_video_time - subscription_purchase_time)) <= 86400 then 1 else 0 end) day1
sum(case when (first_seen_video_time - subscription_purchase_time)) <= 604800 then 1 else 0 end) day7
sum(case when (first_seen_video_time - subscription_purchase_time)) <= 2592000 then 1 else 0 end) day30
from table1
I'm brining first_seen_video_time and subscription_purchase_time from two different CTE's
Where 86400 is 24 hours , 604800 is 7 days and 2592000 is 30 days
How can I get these calculated values for all 30 days without having to hardcode them like this ?

Related

Percentage Difference Using CASE WHEN clause

The table I am working with is called 'transactions'. The columns are id (customer id), amount (amount spent by customer), timestamp (time of purchase).
I am trying to query:
yesterdays revenue: sum of amount.
percent difference from 8 day's ago revenue to yesterday's revenue.
MTD.
percent difference from last months MTD to this months MTD.
SAMPLE DATA
id
amount
timestamp
1
50
2021-12-01
2
60
2021-12-02
3
70
2021-11-05
4
80
2022-01-26
5
90
2022-01-25
6
20
2022-01-26
7
80
2022-01-19
EXPECTED OUTPUT
yesterday_revenue
pct_change_week_ago
mtd
pct_change_month_prior
100
0.25
270
0.50
This is my code. The percent change columns are both incorrect. Please help.
select
-- yesterday
sum(case when timestamp::date = current_date - 1 then amount else null end) yesterday_revenue,
-- yesterday v. last week
(sum(case when timestamp::date > current_date - 1 then amount else null end) - sum(case when timestamp::date = current_date - 8 then amount else null end))
/ sum(case when timestamp::date = current_date - 8 then amount else null end) pct_change_week_ago,
-- mtd
sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) then amount else null end) mtd,
-- mtd v. month prior
(sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) then amount else null end) - sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) - interval '1 month'
and date_part('day',timestamp ) <= date_part('day', CURRENT_DATE -1) then amount else null end))
/ sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) - interval '1 month'
and date_part('day',timestamp ) <= date_part('day', CURRENT_DATE -1) then amount else null end) pct_change_month_prior
from transactions
Some things to consider:
"yesterday vs last week" currently uses timestamp::date > current_date - 1 at the start. This will include transactions from today only, not yesterday (it says "greater than yesterday"). I think it should be timestamp::date = current_date - 1
I could be wrong here, but I think sum(case when date_trunc('month',timestamp) = date_trunc('month',CURRENT_DATE -1) will capture transactions on the current date as well if the current date is in the same month as yesterday. You may not want that.
As far as I can tell, 'pct_change_month_prior' should be 1.45, not 0.5. You have 110 in December and 270 in January. 270 - 110 = 160 and 160 / 110 = 1.45. Your existing query already returns that result. FWIW, you can also use new/old-1 to get the same result in a slightly simpler way.
OK, so really, it's about your maths in the SELECT part of your statement.
Amount changed is: new - old
As a multiplicative amount, it is (new - old) / old or new / old - 1
As a percentage, you need to multiply by 100... 100 * (new / old - 1) but I understand you aren't worried about this.
Further to this, let's make sure your new and old are correct.
Yesterday's sum:
sum(case when timestamp::date = CURRENT_DATE - 1 then amount else null end)
8 days ago sum:
sum(case when timestamp::date = CURRENT_DATE - 8 then amount else null end)
1 month to yesterday sum:
sum(case when timestamp::date > CURRENT_DATE - 1 - INTERVAL '1 month' AND timestamp::date <= CURRENT_DATE - 1 then amount else null end)
1 month to 1 month and 1 day ago sum:
sum(case when timestamp::date > CURRENT_DATE - 1 - INTERVAL '2 month' AND timestamp::date <= CURRENT_DATE - 1 - INTERVAL '1 month' then amount else null end)
Start of month to yesterday sum:
sum(case when timestamp::date > DATE_TRUNC('month', CURRENT_DATE - 1) AND timestamp::date <= CURRENT_DATE - 1 then amount else null end)
Start of yesterday's last month to a month ago yesterday sum:
sum(case when timestamp::date > DATE_TRUNC('month', CURRENT_DATE - 1 - INTERVAL '1 month') AND timestamp::date <= CURRENT_DATE - 1 - INTERVAL '1 month' then amount else null end)
It's important you don't change = to > or cropping to just the date part else you will include more than you really want.
Effectively, by cropping to the month part, it would almost always sum all transactions for two months.

DB2 issue with CASE and adding days to date

I'm trying to get a selection of records where the date field of the record(s) is current date + 7 Days
I was previously doing this in MySQL like so:
SUM(CASE WHEN ( d.next_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS dateCount
But now trying to do this on DB2 it's not working
SUM(case WHEN f.next_date + 7 days then 1 else 0 end) as dateCount
I'm wondering why this would be, but I'm simply trying to get a count of all records where the date is today + 7 days.
What am I doing wrong
Your case expression is lacking a comparison, e.g. when (some_value is compared to other_value) then do_something .... Perhaps an equal?
SUM(case when {date field of the record} = f.next_date + 7 days then 1 else 0 end) as dateCount
Try this:
select sum(case when f.next_date = current date + 7 day then 1 end) as dateCount
from table(values
current date + 1 day
, current date + 7 day
, current date + 7 day
) f(next_date);

SQL Table UPDATE by row with days per month

SQL Server 2005:
I'm attempting to create a table that looks like this:
JAN | FEB | March .......Dec | YTD
Total Volume:
Days in Month:
Gallons per day AVG:
Three rows with description on left, 13 columns (one for each month and year to date total).
I know how to populate the total volume per month. What would I use for days per month and average? I'd like the days per month to show either the complete number of days if it is a past month or current completed days if its the current month.
You are pivoting the data, so you want the results in columns. You can do this by using direct calculation. Here is an example for the first three months:
select 'Days In Month' as col1,
(case when month(getdate()) < 1 then 0
when month(getdate()) = 1 then day(getdate())
else 31
end) as Jan,
(case when month(getdate()) < 2 then 0
when month(getdate()) = 2 then day(getdate())
when year(getdate()) % 4 = 0 then 29
else 28
end) as Feb,
(case when month(getdate()) < 3 then 0
when month(getdate()) = 3 then day(getdate())
else 31
end) as Mar,

SQL script to check a value then if found increment a field by a value of 1

Im trying to write a script that will pull the information from a table called 'bookings', this contains a column that gives the length of each booking called 'hours'. Values in this column are shown as 1.0 for 60 minutes, 0.75 for 45 minutes, 0.5 for 30 minutes for example. My script needs to count the amount of bookings of a particular length and return the value, so for example I am using a Sum and Case statment for each...
SUM(case when Hours = 1 then 1 else 0 end) as '60 Mins',
SUM(case when Hours = 0.75 then 1 else 0 end) as '45 Mins',
SUM(case when Hours = 0.5 then 1 else 0 end) as '30 Mins',
SUM(case when Hours = 0.25 then 1 else 0 end) as '15 Mins'
My problem is that I need to record bookings over 60 minutes and split them into one of these four groups, an example is 1.5 hours would need to add a value of +1 to the 60 minute case statement and also +1 count to the 30 minute case statement value,
The only way I could think of doing that is to create a temporary table with columns for 60, 45, 30 and 15 count values then update this table by +1 if a result is found, so 1.25 would then update #temptable column(60) +1 and column(15)+1. Not sure how to do this, help greatly appreciated.
Thanks
Simon
Have a look at this sql fiddle. Hopefully that is enough to get you started.
select hours
,100*(hours - round(hours,0,1))
from table1
so your code would be something like
SUM(case when hours - round(hours,0,1) = 0 then 1 else 0 end) as '60 Mins',
SUM(case when hours - round(hours,0,1) = 0.75 then 1 else 0 end) as '45 Mins',
SUM(case when hours - round(hours,0,1) = 0.5 then 1 else 0 end) as '30 Mins',
SUM(case when hours - round(hours,0,1) = 0.25 then 1 else 0 end) as '15 Mins'

T-SQL Question - Counting and Average

I have a set of data that consists of a filenbr, open date and close date.
I need to produce a summary table similar to the below, i need to count how many files belong to each day period, but i need those greater than 20 grouped together. I know how to get the datediff, what i'm stumbling on is how to get the 20+ and the % column
1 day - 30 files - 30%
3 days - 25 files - 25%
10 days - 5 files - 5%
13 days - 20 files - 20%
>= 20 days - 20 files - 20%
suppose you have a table named dayFile with the following columns
Table DayFile
days - files
1 - 10
1 - 5
1 - 15
3 - 20
3 - 5
10 - 5
13 - 20
20 - 5
22 - 5
28 - 10
Then you could do the following
SELECT
SummaryTable.Day,
SUM(SummaryTable.Files) as SumFiles,
Sum(SummaryTable.Files) / SummaryTable.TotalFiles
FROM
(SELECT
CASE WHEN (days >= 20) THEN
20
ELSE DF.days END as Day
files,
(SELECT Count(*) FROM DayFile DFCount) as TotalFiles
FROM DayFile DF) SummaryTable
Group By SummaryTable.Day
EDITED:
SELECT
SummaryTable.Day,
SUM(SummaryTable.Files) as SumFiles,
Sum(SummaryTable.Files) / (SELECT Count(*) FROM DayFile DFCount)
FROM
(SELECT
CASE WHEN (days >= 20) THEN
20
ELSE DF.days END as Day
files
FROM DayFile DF) SummaryTable
Group By SummaryTable.Day
You are unclear as to how the ranges are determined (e.g. does "3 days mean < 3 days, <= 3 days, = 3 days, > 3 days or >= 3 days?). If you are using SQL Server 2005 and higher, you get your results like so:
With PeriodLength As
(
Select DateDiff(d, OpenDate, CloseDate) As DiffDays
From Table
)
, Ranges As
(
Select Case
When DiffDays < 3 Then 'Less than 3 Days'
When DiffDays >= 3 And DiffDays < 10 Then 'Less than 10 Days'
When DiffDays >= 10 And DiffDays < 13 Then 'Less than 13 Days'
When DiffDays >= 13 And DiffDays < 20 Then 'Less than 20 Days'
When DiffDays >= 20 Then 'Greater than 20 days'
End As Range
From PeriodLength
)
Select Range
, Count(*) As FileCount
, Count(*) * 100.000 / (Select Count(*) From Ranges) As Percentage
From Ranges
Group By Range