我有一个场景。这是我的表格结构:
ID LoginDate RemovalDate
----------------------------------------
1 2009/08/01 NULL
2 2009/09/12 2010/01/02
3 2009/08/31 2009/10/29
4 2010/02/17 NULL
5 2009/10/18 2009/11/22
我想要一个合并的结果,表明在特定月份没有删除多少ID。所以结果集应该是
Date NotRemoved_ID
--------------------------
2009/08 2
2009/09 3
2009/10 3 [One ID got removed in 2009/10]
2010/02 2 [Two got removed in 2009/11 and 2010/01]
请帮忙。
答案 0 :(得分:1)
WITH a AS (SELECT CAST('20090801' AS datetime) LoginDate,
CAST(NULL AS datetime) RemovalDate
UNION ALL SELECT '20090912', '20100102'
UNION ALL SELECT '20090831', '20091029'
UNION ALL SELECT '20100217', NULL
UNION ALL SELECT '20091018', '20091122'),
b AS (SELECT LoginDate [Date], 1 [Amount] FROM a
UNION ALL SELECT RemovalDate, -1 FROM a),
c AS (SELECT DATEADD(month, DATEDIFF(month, 0, [Date]), 0) [Month], [Amount]
FROM b),
d AS (SELECT [Month], SUM([Amount]) [Amount] FROM c GROUP BY [Month]),
e AS (SELECT d.[Month], SUM(d2.[Amount]) [Amount]
FROM d JOIN d d2 ON d2.[Month] <= d.[Month] GROUP BY d.[Month])
SELECT [Month], [Amount] FROM e
答案 1 :(得分:1)
远非漂亮,可能还需要进行优化,但这已经过测试并可与SQL Server配合使用。
确保用实际的tabelname替换对@Table的所有引用。
DECLARE @Table TABLE (ID INTEGER, LoginDate DATETIME, RemovalDate DATETIME)
INSERT INTO @Table
SELECT 1, '2009/08/01', NULL
UNION ALL SELECT 2, '2009/09/12', '2010/01/02'
UNION ALL SELECT 3, '2009/08/31', '2009/10/29'
UNION ALL SELECT 4, '2010/02/17', NULL
UNION ALL SELECT 5, '2009/10/18', '2009/11/22'
SELECT CAST(ld.yr AS VARCHAR(4)) + '/' + RIGHT('0' + CAST(ld.mnth AS VARCHAR(2)), 2), ld.RunningTotal - ISNULL(rd.RunningTotal, 0)
FROM (
SELECT yr, mnth, RunningTotal = MAX(RunningTotal)
FROM (
SELECT yr = YEAR(t1.LoginDate), mnth = MONTH(t1.LoginDate), RunningTotal = COUNT(*)
FROM @Table t1
CROSS JOIN @Table t2
WHERE t1.LoginDate >= t2.LoginDate
GROUP BY t1.LoginDate
) ld
GROUP BY ld.yr, ld.mnth
) ld
LEFT OUTER JOIN (
SELECT yr, mnth, RunningTotal = MAX(RunningTotal)
FROM (
SELECT yr = YEAR(t1.RemovalDate), mnth = MONTH(t1.RemovalDate), RunningTotal = COUNT(*)
FROM @Table t1
CROSS JOIN @Table t2
WHERE t1.RemovalDate >= t2.RemovalDate
GROUP BY t1.RemovalDate
) ld
GROUP BY ld.yr, ld.mnth
) rd ON rd.yr <= ld.yr AND rd.mnth <= ld.mnth
ORDER BY
1, 2
答案 2 :(得分:0)
我认为你可以这样做:
Select LoginDate , dbo.fn_NotRemoved( LoginDate ) From YourTable
因此您可以根据需要编写fn_NotRemoved。但是,应考虑这种方式的性能缺陷。
希望这会有所帮助