2015-06-10 51 views
2

我有一张表,其中包含很多行(目前500K,预计在未来3年内将增加到1500万)。该表包含针对特定日期的特定活动进行的付款。事件可以在同一天进行一次或多次付款,但同一天的付款必须具有不同的付款类型。获取连续的日期范围分组为一行

下面是创建基本数据(输入),然后硬编码选择哪个是预期输出的表变量创建。我需要将支付类型的连续日期范围,一个展示位置的连续日期范围与From和To日期一起分组,然后在发生中断时 - 没有行,然后是下一个日期范围。

例如:

放置1获得从第一支付给第二(2天)付款类型5,然后从第四直到第六为相同的类型。因此,两排。付款类型1还支付第一至第三付款类型10.因此,这是另一行。

DECLARE @Temp TABLE 
(
    Id INT NOT NULL IDENTITY(1,1), 
    PlacementId INT NOT NULL, 
    PaymentTypeId INT NOT NULL, 
    DateValue DATETIME NOT NULL, 
    Amount DECIMAL(16,2) NOT NULL 
) 

INSERT INTO @Temp (PlacementId, PaymentTypeId, DateValue, Amount) 
SELECT 1, 5, '01-JAN-2015', 100 UNION 
SELECT 1, 5, '02-JAN-2015', 150 UNION 
SELECT 1, 5, '04-JAN-2015', 78 UNION 
SELECT 1, 5, '05-JAN-2015', 89 UNION 
SELECT 1, 5, '06-JAN-2015', 22 UNION 
SELECT 1, 10, '01-JAN-2015', 10 UNION 
SELECT 1, 10, '02-JAN-2015', 10 UNION 
SELECT 1, 10, '03-JAN-2015', 15 UNION 
SELECT 2, 5, '01-JAN-2015', 200 UNION 
SELECT 2, 5, '02-JAN-2015', 5 UNION 
SELECT 2, 5, '03-JAN-2015', 50 UNION 
SELECT 3, 5, '01-JAN-2015', 80 UNION 
SELECT 4, 5, '07-JAN-2015', 100 UNION 
SELECT 4, 5, '08-JAN-2015', 12 UNION 
SELECT 4, 5, '12-JAN-2015', 66 UNION 
SELECT 4, 5, '14-JAN-2015', 4 UNION 
SELECT 5, 10, '08-JAN-2015', 10 

SELECT * FROM @Temp 

SELECT 1 AS PlacementId, 5 AS PaymentTypeId, '2015-01-01' AS FromDate, '2015-01-02' AS ToDate, 250 AS Amount UNION 
SELECT 1, 10, '2015-01-01', '2015-01-03', 35 UNION 
SELECT 1, 5, '2015-01-04', '2015-01-06', 189 UNION 
SELECT 2, 5, '2015-01-01', '2015-01-03', 255 UNION 
SELECT 3, 5, '2015-01-01', '2015-01-01', 80 UNION 
SELECT 4, 5, '2015-01-07', '2015-01-08', 112 UNION 
SELECT 4, 5, '2015-01-12', '2015-01-12', 66 UNION 
SELECT 4, 5, '2015-01-14', '2015-01-14', 4 UNION 
SELECT 5, 10, '2015-01-08', '2015-01-08', 10 

注意,在PlacementID和PaymentTypeID上有一个NCI。

我们现在正在做一个疯狂的游标加载,并且出现极速问题。 (500K线需要4分钟处理)。

是否有一种有效的方法来实现所需的输出?

+0

是的,正确的!抱歉。我会解决这个问题。 – Craig

+0

对于'PlacementId = 1'和'PaymentTypeId = 10',如果金额等于'35','10 + 10 + 15'? –

回答

2

这是一个问题,称为分组群岛的连续日期。阅读此article是Jeff Moden的更多信息。

SQL Fiddle

;WITH Cte AS(
    SELECT *, 
     RN = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY PlacementId, PaymentTypeId ORDER BY DateValue), DateValue) 
    FROM @Temp 
) 
SELECT 
    PlacementId, 
    PaymentTypeId, 
    FromDate = MIN(DateValue), 
    ToDate = MAX(DateValue), 
    Amount = SUM(Amount) 
FROM Cte 
GROUP BY PlacementId, PaymentTypeId, RN 
ORDER BY PlacementId, PaymentTypeId, FromDate 
+0

@克雷格,没问题。很高兴我能帮上忙。 –