Home > Mobile >  How to count the number of campaigns per day based on the start and end dates of the campaigns in SQ
How to count the number of campaigns per day based on the start and end dates of the campaigns in SQ

Time:10-21

I need to count the number of campaigns per day based on the start and end dates of the campaigns

Input Table:

Campaign name Start date End date
Campaign A 2022-07-10 2022-09-25
Campaign B 2022-08-06 2022-10-07
Campaign C 2022-07-30 2022-09-10
Campaign D 2022-08-26 2022-10-24
Campaign E 2022-07-17 2022-09-29
Campaign F 2022-08-24 2022-09-12
Campaign G 2022-08-11 2022-10-24
Campaign H 2022-08-26 2022-11-22
Campaign I 2022-08-29 2022-09-25
Campaign J 2022-08-21 2022-11-15
Campaign K 2022-07-20 2022-09-18
Campaign L 2022-07-31 2022-11-20
Campaign M 2022-08-17 2022-10-10
Campaign N 2022-07-27 2022-09-07
Campaign O 2022-07-29 2022-09-26
Campaign P 2022-07-06 2022-09-15
Campaign Q 2022-07-16 2022-09-22

Out needed (result):

Date Count unique campaigns
2022-07-02 17
2022-07-03 47
2022-07-04 5
2022-07-05 5
2022-07-06 25
2022-07-07 27
2022-07-08 17
2022-07-09 58
2022-07-10 23
2022-07-11 53
2022-07-12 18
2022-07-13 29
2022-07-14 52
2022-07-15 7
2022-07-16 17
2022-07-17 37
2022-07-18 33

How do I need to write the SQL command to get the above result? thanks all

CodePudding user response:

Your sample data doesn't seem to match your desired results, but I think what you're after is this:

DECLARE @Start date, @End date;

-- first, find the earliest and last date:

SELECT @Start = MIN([Start date]), @End = MAX([End date])
  FROM dbo.Campaigns;

-- now use a recursive CTE to build a date range, 
-- and count the number of campaigns that have a row
-- where the campaign was active on that date:

WITH d(d) AS 
(
  SELECT @Start 
  UNION ALL 
  SELECT DATEADD(DAY, 1, d) FROM d WHERE d < @End
)
SELECT 
  [Date] = d, 
  [Count unique campaigns] = COUNT(*) 
FROM d 
INNER JOIN dbo.Campaigns AS c
ON d.d >= c.[Start date] AND d.d <= c.[End date]
GROUP BY d.d OPTION (MAXRECURSION 32767);

Working example in this fiddle.

CodePudding user response:

In the following solutions we leverage string_split with combination with replicate to generate new records.

select   dt        as date
        ,count(*)  as Count_unique_campaigns

from      
(
select    *
         ,dateadd(day, row_number() over(partition by Campaign_name  order by (select null))-1, Start_date) as dt
from     (
         select   *
         from     t
         outer apply string_split(replicate(',',datediff(day, Start_date, End_date)),',')
         ) t
) t
group by dt
order by dt
date Count_unique_campaigns
2022-07-06 1
2022-07-07 1
2022-07-08 1
2022-07-09 1
2022-07-10 2
2022-07-11 2
2022-07-12 2
2022-07-13 2
2022-07-14 2
2022-07-15 2
2022-07-16 3
2022-07-17 4
2022-07-18 4
2022-07-19 4
2022-07-20 5
2022-07-21 5
2022-07-22 5
2022-07-23 5
2022-07-24 5
2022-07-25 5
2022-07-26 5
2022-07-27 6
2022-07-28 6
2022-07-29 7
2022-07-30 8
2022-07-31 9
2022-08-01 9
2022-08-02 9
2022-08-03 9
2022-08-04 9
2022-08-05 9
2022-08-06 10
2022-08-07 10
2022-08-08 10
2022-08-09 10
2022-08-10 10
2022-08-11 11
2022-08-12 11
2022-08-13 11
2022-08-14 11
2022-08-15 11
2022-08-16 11
2022-08-17 12
2022-08-18 12
2022-08-19 12
2022-08-20 12
2022-08-21 13
2022-08-22 13
2022-08-23 13
2022-08-24 14
2022-08-25 14
2022-08-26 16
2022-08-27 16
2022-08-28 16
2022-08-29 17
2022-08-30 17
2022-08-31 17
2022-09-01 17
2022-09-02 17
2022-09-03 17
2022-09-04 17
2022-09-05 17
2022-09-06 17
2022-09-07 17
2022-09-08 16
2022-09-09 16
2022-09-10 16
2022-09-11 15
2022-09-12 15
2022-09-13 14
2022-09-14 14
2022-09-15 14
2022-09-16 13
2022-09-17 13
2022-09-18 13
2022-09-19 12
2022-09-20 12
2022-09-21 12
2022-09-22 12
2022-09-23 11
2022-09-24 11
2022-09-25 11
2022-09-26 9
2022-09-27 8
2022-09-28 8
2022-09-29 8
2022-09-30 7
2022-10-01 7
2022-10-02 7
2022-10-03 7
2022-10-04 7
2022-10-05 7
2022-10-06 7
2022-10-07 7
2022-10-08 6
2022-10-09 6
2022-10-10 6
2022-10-11 5
2022-10-12 5
2022-10-13 5
2022-10-14 5
2022-10-15 5
2022-10-16 5
2022-10-17 5
2022-10-18 5
2022-10-19 5
2022-10-20 5
2022-10-21 5
2022-10-22 5
2022-10-23 5
2022-10-24 5
2022-10-25 3
2022-10-26 3
2022-10-27 3
2022-10-28 3
2022-10-29 3
2022-10-30 3
2022-10-31 3
2022-11-01 3
2022-11-02 3
2022-11-03 3
2022-11-04 3
2022-11-05 3
2022-11-06 3
2022-11-07 3
2022-11-08 3
2022-11-09 3
2022-11-10 3
2022-11-11 3
2022-11-12 3
2022-11-13 3
2022-11-14 3
2022-11-15 3
2022-11-16 2
2022-11-17 2
2022-11-18 2
2022-11-19 2
2022-11-20 2
2022-11-21 1
2022-11-22 1

For SQL in Azure and SQL Server 2022 we have a cleaner solution based on [ordinal][4].

"The enable_ordinal argument and ordinal output column are currently supported in Azure SQL Database, Azure SQL Managed Instance, and Azure Synapse Analytics (serverless SQL pool only). Beginning with SQL Server 2022 (16.x) Preview, the argument and output column are available in SQL Server."

select   dt        as date
        ,count(*)  as Count_unique_campaigns

from      
(
select    *
         ,dateadd(day, ordinal-1, Start_date) as dt
from     (
         select   *
         from     t
         outer apply string_split(replicate(',',datediff(day, Start_date, End_date)),',', 1)
         ) t
) t
group by dt
order by dt

Fiddle

  • Related