按日期范围分组在t-sql中

Kob*_* to 5 sql t-sql sql-server

我正在尝试对此表进行查询:

Id       startdate     enddate       amount
1        2013-01-01   2013-01-31      0.00
2        2013-02-01   2013-02-28      0.00
3        2013-03-01   2013-03-31      245
4        2013-04-01   2013-04-30      529
5        2013-05-01   2013-05-31      0.00
6        2013-06-01   2013-06-30      383
7        2013-07-01   2013-07-31      0.00
8        2013-08-01   2013-08-31      0.00
Run Code Online (Sandbox Code Playgroud)

我想获得输出:

2013-01-01          2013-02-28          0
2013-03-01          2013-06-30          1157
2013-07-01          2013-08-31           0
Run Code Online (Sandbox Code Playgroud)

我想得到那个结果,所以我知道什么时候开始进货以及什么时候停止.我也对钱开始进入之前的几个月(第一行解释)以及资金停止的月数感兴趣(这也解释了为什么我对2013年7月到2013年8月的第3行感兴趣).

我知道我可以在日期上使用最小值和最大值并总结金额,但我无法弄清楚如何将记录划分为这种方式.
谢谢!

lc.*_*lc. 2

这是一个想法(以及与之相配的小提琴):

;WITH MoneyComingIn AS
(
    SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, 
        SUM(amount) AS amount
    FROM myTable
    WHERE amount > 0
)
SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, 
    SUM(amount) AS amount
FROM myTable
WHERE enddate < (SELECT startdate FROM MoneyComingIn)
UNION ALL
SELECT startdate, enddate, amount
FROM MoneyComingIn
UNION ALL
SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, 
    SUM(amount) AS amount
FROM myTable
WHERE startdate > (SELECT enddate FROM MoneyComingIn)
Run Code Online (Sandbox Code Playgroud)

第二个,不使用UNIONfiddle):

SELECT MIN(startdate), MAX(enddate), SUM(amount)
FROM
(
    SELECT startdate, enddate, amount,
    CASE 
        WHEN EXISTS(SELECT 1 
                    FROM myTable b 
                    WHERE b.id>=a.id AND b.amount > 0) THEN
            CASE WHEN EXISTS(SELECT 1 
                             FROM myTable b 
                             WHERE b.id<=a.id AND b.amount > 0) 
                 THEN 2 
                 ELSE 1 
            END
        ELSE 3
    END AS partition_no
    FROM myTable a
) x
GROUP BY partition_no
Run Code Online (Sandbox Code Playgroud)

尽管我认为所写的它假设Id是有序的。您可以用ROW_NUMBER() OVER(ORDER BY startdate).