我有一个SQL请求,我似乎无法理解。
我有一张桌子"订阅"包含registrationDate,startDate和endDate。
字段registrationDate基本上包含条目创建日期。 (客户订阅的日期) 字段startDate包含订阅将变为"活动"的日期。 字段endDate包含不考虑订阅的日期"活动"了。
在以下示例中,横轴表示两个选定日期(此处为2012-01和2012-04)之间可能的所有注册月份。纵轴表示可以考虑订阅的所有月份"活动"在第一个选定日期(2012-01)和所选日期之后三年之间。 (如果我们拥有所需的所有数据,总共36个月)
以下是我的一个请求的结果。
你可以在每一行看到数字" nb"在月份期间创建的订阅" registrationDate",在" startDate"期间开始并在" endDate"。
期间结束我的问题是,我不知道如何知道在2012-01或其他任何月份变为活动的订阅在一个或一个月之后仍然有效。
注意:我必须在一个sql请求中执行所有操作。矩阵由它生成。
这是我试过的一些方法。结果是不一致/不满意的:
//1----------------------
SELECT
CONVERT(varchar(7), sub.startDate, 102) as regMonth
,CONVERT(varchar(7), sub.registrationDate, 102) as actMonth
,COUNT(sub.id)
FROM Subscription as sub
WHERE
sub.registrationDate >= '2012-01-01'
AND sub.registrationDate <= '2013-01-01'
AND sub.startDate >= sub.registrationDate
AND sub.endDate <= DATEADD(year, 3, '2012-01-01')
GROUP BY
CONVERT(varchar(7), sub.startDate, 102)
,CONVERT(varchar(7), sub.registrationDate, 102)
ORDER BY
regMonth
,actMonth
//2----------------------
SELECT
CONVERT(varchar(7), sub.registrationDate, 102) as regMonth
,CONVERT(varchar(7), act.startDate, 102) as actMonth
,COUNT(act.id) as nbActive
FROM Subscription as sub
JOIN Subscription as act ON act.clientId = sub.clientId
AND act.startDate >= sub.registrationDate
AND act.startDate <= DATEADD(year, 3, '2012-01-01')
WHERE
sub.registrationDate >= '2012-01-01'
AND sub.registrationDate <= '2013-01-01'
GROUP BY
CONVERT(varchar(7), sub.registrationDate, 102),
CONVERT(varchar(7), act.startDate, 102)
ORDER BY regMonth, actMonth
Here are some data sample。日期从2010年到2014年。
感谢您的帮助!
我也会发布我的进展。
答案 0 :(得分:0)
以下是示例表
CREATE TABLE #TEMP(STARTDATE DATE,ENDDATE DATE,registrationDate DATE)
INSERT INTO #TEMP
SELECT '2012-04-23','2012-07-23','2012-04-23'
UNION ALL
SELECT '2012-05-23','2012-07-23','2012-04-23'
UNION ALL
SELECT '2012-06-23','2013-01-23','2012-04-23'
UNION ALL
SELECT '2012-01-23','2012-03-23','2012-05-23'
UNION ALL
SELECT '2012-04-23','2012-07-23','2012-05-23'
UNION ALL
SELECT '2012-06-23','2012-06-23','2012-07-23'
UNION ALL
SELECT '2012-07-23','2012-10-23','2012-07-23'
以下是pivot之前的查询
;WITH CTE AS
(
-- Filters according to year and get the Id for each StartDate for each registrationDate
SELECT ROW_NUMBER() OVER(PARTITION BY registrationDate ORDER BY STARTDATE)RNO,*
FROM #TEMP
WHERE [endDate]<DATEADD(YEAR,3,[startDate])
)
,CTE2 AS
(
-- Get all months between the StartDate and EndDate
SELECT RNO,registrationDate,STARTDATE ,ENDDATE
FROM CTE
UNION ALL
SELECT CTE2.RNO,CTE2.registrationDate,DATEADD(MONTH,1,CTE2.STARTDATE),CTE2.ENDDATE
FROM CTE
JOIN CTE2 ON CTE2.registrationDate = CTE.registrationDate AND CTE2.RNO = CTE.RNO
WHERE CTE2.STARTDATE < CTE2.ENDDATE
)
-- Keeps an extra column to pivot and gets the count of each date for each registrationDate
SELECT DISTINCT registrationDate,STARTDATE [MONTHS],COUNT(STARTDATE) OVER(PARTITION BY registrationDate,STARTDATE) CNT,
CAST(YEAR(registrationDate)AS VARCHAR(4))+'/'+CAST(MONTH(registrationDate)AS VARCHAR(2)) COLS
INTO #NEWTABLE
FROM CTE2
ORDER BY registrationDate,STARTDATE
OPTION(MAXRECURSION 0)
获取枢轴列
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + COLS + ']',
'[' + COLS + ']')
FROM (SELECT DISTINCT registrationDate,COLS FROM #NEWTABLE) PV
ORDER BY registrationDate
现在转动它
DECLARE @query NVARCHAR(MAX)
SET @query = '
SELECT CAST(YEAR(MONTHS)AS VARCHAR(4))+''/''+CAST(MONTH(MONTHS)AS VARCHAR(2)) [ACTIVE MONTH]
,' + @cols + '
FROM
(
SELECT [MONTHS],COLS,CNT FROM #NEWTABLE
) x
PIVOT
(
MIN(CNT)
FOR [COLS] IN (' + @cols + ')
) p
ORDER BY MONTHS
'
EXEC SP_EXECUTESQL @query
希望它有所帮助。