确定单个日期范围与四个日期范围中的哪一个重叠



我的订阅可以持续 1 到 4 个财政季度(也可以看作是四个日期范围(的任何地方(就我的输出而言(

我正在使用亚利桑那州财政季度:

  • Q1:7月1日至9月30日
  • 第二季度:10月1日至12月31
  • 第 3 季度:1 月 1 日至 3 月 31 日
  • 第四季度:4月1日至6月30日

我需要弄清楚的是,根据订阅开始和结束日期,每个季度有多少订阅处于活动状态。

例如,使用 (YYYY-MM-DD(,我有:

  • 从 2016-07-06 开始到 2017-02-22 结束的订阅 我应该能够看到我在第 1 季度、第 2 季度和第 3 季度有一个有效的订阅。
  • 另一个从 2016-10-18 开始到 2016-10-24 结束的订阅只会被视为在第二季度处于活动状态
  • 最后,从
  • 2016-09-28 开始但没有结束日期的订阅将被视为在 Q1、Q2、Q3 和 Q4 处于活动状态(因此,无论从哪个开始季度一直到 Q4(

下面是我当前的SQL Server脚本,这里是SQL Fiddle上的:

WITH SubscriptionInfo AS
(
SELECT
[Subscriptions].[Customer_Id]
,[DistributorTypes].[Name]                              AS [Distributor Type]
,[Customers].Zip_Id
,[Subscriptions].[UnsubscribeReason_Id]
,[Subscriptions].[Id]                                   AS [Subscription ID]
,CONVERT(DATE, [Subscriptions].[StartDate])             AS [Subscription Start Date]
,CONVERT(DATE, [Subscriptions].[EndDate])               AS [Subscription End Date]
,[PriorityLevels].PriorityLevel                         AS [Priority Level]
,CONVERT(DATE, [SubscriptionPriorityLevels].StartDate)  AS [Priority Level Start Date]
,CONVERT(DATE, [SubscriptionPriorityLevels].EndDate)    AS [Priority Level End Date]
,[FundingSources].[Name]                                AS [Funding Source]
,CONVERT(DATE, [SubscriptionFundingSources].StartDate)  AS [SubscriptionFundingSources Start Date]
,CONVERT(DATE, [SubscriptionFundingSources].EndDate)    AS [SubscriptionFundingSources End Date]
FROM [Subscriptions]
LEFT JOIN [SubscriptionPriorityLevels]
ON [SubscriptionPriorityLevels].Subscription_Id = Subscriptions.Id
LEFT JOIN [PriorityLevels]
ON [PriorityLevels].Id = SubscriptionPriorityLevels.PriorityLevel_Id
LEFT JOIN [SubscriptionFundingSources]
ON [SubscriptionFundingSources].Subscription_Id = Subscriptions.Id
LEFT JOIN [FundingSources]
ON [FundingSources].Id = [SubscriptionFundingSources].FundingSource_Id
LEFT JOIN [Customers]
ON [Customers].Id = [Subscriptions].Customer_Id
LEFT JOIN [DistributorTypes]
ON [DistributorTypes].Id = Customers.DistributorType_Id
WHERE
([Subscriptions].StartDate >= '2016-07-01')             -- Dummy dates, would later be parameters
AND ([Subscriptions].EndDate <= '2017-06-30'
OR [Subscriptions].EndDate IS NULL)
AND ([PriorityLevels].PriorityLevel IN (2, 3))          -- Only care about these two levels
AND ([Customers].DistributorType_Id = 1)                -- Distributor Type: Number One Distrubition
AND ([SubscriptionFundingSources].FundingSource_Id = 2) -- Funding Source: First Bank
)
SELECT
[SubscriptionInfo].Customer_Id
,[SubscriptionInfo].[Subscription ID]
,MAX([SubscriptionInfo].[Priority Level]) AS [Highest Priority Level]
,CASE   -- Determine which fiscal quarter each Subscription Start Date belongs to
WHEN MONTH([SubscriptionInfo].[Subscription Start Date]) IN (7, 8, 9)       THEN 1  -- July, August, September
WHEN MONTH([SubscriptionInfo].[Subscription Start Date]) IN (10, 11, 12)    THEN 2  -- October, November, December
WHEN MONTH([SubscriptionInfo].[Subscription Start Date]) IN (1, 2, 3)       THEN 3  -- January, Feburary, March
              ELSE 4  -- April, May, June
END AS [Fiscal Quarter Start Date]
,CASE   -- Determine which fiscal quarter each Subscription Start Date belongs to
WHEN MONTH([SubscriptionInfo].[Subscription End Date]) IN (7, 8, 9)         THEN 1  -- July, August, September
WHEN MONTH([SubscriptionInfo].[Subscription End Date]) IN (10, 11, 12)      THEN 2  -- October, November, December
WHEN MONTH([SubscriptionInfo].[Subscription End Date]) IN (1, 2, 3)         THEN 3  -- January, Feburary, March
              ELSE 4  -- April, May, June
END AS [Fiscal Quarter End Date]
FROM [SubscriptionInfo]

GROUP BY
[SubscriptionInfo].Customer_Id
,[SubscriptionInfo].[Subscription ID]
,CASE   -- Group Subscription Start Date's into Fiscal Quarters
WHEN MONTH([SubscriptionInfo].[Subscription Start Date]) IN (7, 8, 9)       THEN 1  -- July, August, September
WHEN MONTH([SubscriptionInfo].[Subscription Start Date]) IN (10, 11, 12)    THEN 2  -- October, November, December
WHEN MONTH([SubscriptionInfo].[Subscription Start Date]) IN (1, 2, 3)       THEN 3  -- January, Feburary, March
              ELSE 4  -- April, May, June
END
,CASE   -- Group Subscription End Date's into Fiscal Quarters
WHEN MONTH([SubscriptionInfo].[Subscription End Date]) IN (7, 8, 9)         THEN 1  -- July, August, September
WHEN MONTH([SubscriptionInfo].[Subscription End Date]) IN (10, 11, 12)      THEN 2  -- October, November, December
WHEN MONTH([SubscriptionInfo].[Subscription End Date]) IN (1, 2, 3)         THEN 3  -- January, Feburary, March
              ELSE 4  -- April, May, June
END
ORDER BY
[SubscriptionInfo].Customer_Id

到目前为止,我能够确定订阅在哪个财政季度开始以及哪个财政季度结束。

我希望能够计算每个季度有多少订阅处于活动状态。

期望输出:

| FirstQuarter | SecondQuarter | ThirdQuarter | FourthQuarter |
|--------------|---------------|--------------|---------------|
|            2 |             1 |            3 |             3 |

一旦您按照朗格的建议有了描述季度开始和结束日期@Sean表格,您只需要将订阅的开始和结束日期与季度的开始和结束日期进行比较,然后将它们计算在重叠的地方。 基本上,如果 A.StartB.Start,则两个范围有一些重叠。

下面是该模式的完整示例。

-------------------------
-- construct the quarters table (taken from the SQL Fiddle in comments above)
DECLARE @FiscalDate Table
(
Id INT NOT NULL,
FiscalYear INT NOT NULL,
FiscalQuarter INT NOT NULL,
QuarterStartDate DATE NOT NULL,
QuarterEndDate DATE NOT NULL
PRIMARY KEY(Id)
);
INSERT INTO @FiscalDate 
(Id, FiscalYear, FiscalQuarter, QuarterStartDate, QuarterEndDate)
VALUES
( 1, 2016, 1, '2016-07-01', '2016-09-30')
,(2, 2016, 2, '2016-10-01', '2016-12-31')
,(3, 2017, 3, '2017-01-01', '2017-03-31')
,(4, 2017, 4, '2017-04-01', '2017-06-30')
;

-------------------------
--Get some random test data to imitate subscriptions ranges
DECLARE @tempSet Table(a date, b date)
INSERT INTO @tempSet SELECT TOP 15
dateadd(dd, ROUND(365 * RAND(convert(varbinary, newid())), 0), '2016-07-01') as a
, dateadd(dd, ROUND(365 * RAND(convert(varbinary, newid())), 0), '2016-07-01') as b
FROM sysobjects
-------------------------
-- Fix our random data a little (start date needs to be before end date)
DECLARE @DateRanges Table(StartDate date, EndDate date)
INSERT INTO @DateRanges
SELECT a, b FROM @tempset WHERE a <= b UNION SELECT b, a FROM @tempset WHERE b < a

-------------------------
-- Show our Date ranges in a useful order for review
SELECT * FROM @DateRanges ORDER BY StartDate, EndDate
-------------------------
-- Show our by-quarter counts.

SELECT
fd.FiscalQuarter
, count(*) as ActiveSubsCount
FROM
@FiscalDate fd
JOIN
@DateRanges dr
on fd.QuarterStartDate < dr.EndDate
and fd.QuarterEndDate >= dr.StartDate
GROUP BY
fd.FiscalQuarter

-------------------------
-- and in your desired output (without your quarters table)
SELECT
COUNT(CASE WHEN '2016-07-01' < dr.EndDate AND '2016-09-30' >= dr.StartDate THEN 1 ELSE NULL END) AS FirstQuarter 
, COUNT(CASE WHEN '2016-10-01' < dr.EndDate AND '2016-12-31' >= dr.StartDate THEN 1 ELSE NULL END) AS SecondQuarter  
, COUNT(CASE WHEN '2017-01-01' < dr.EndDate AND '2017-03-31' >= dr.StartDate THEN 1 ELSE NULL END) AS ThirdQuarter 
, COUNT(CASE WHEN '2017-04-01' < dr.EndDate AND '2017-06-30' >= dr.StartDate THEN 1 ELSE NULL END) AS FourthQuarter 
FROM
@DateRanges dr

最新更新