2016-11-22 30 views
3

我有如下SQL Server中的表,SQL服務器做這樣集團通過任務

Date  Value 
--------------------------------------------------- 
08-01-2016 1 
08-02-2016 1 
08-03-2016 1 
08-04-2016 1 
08-05-2016 1 
08-06-2016 2 
08-07-2016 2 
08-08-2016 2 
08-09-2016 2.5 
08-10-2016 1 
08-11-2016 1 

由於原來的表格太大,即使我用「結果到文件」,但仍引發異常'System.OutOfMemoryException的'。這就是爲什麼我想組織這種表格。

但我沒有一個好的邏輯來處理。因此,我想將表格更改爲以下類型。

Date_from  Date_to  Value 
------------------------------------------------- 
08-01-2016  08-05-2016 1 
08-06-2016  08-08-2016 2 
08-09-2016  08-09-2016 2.5 
08-10-2016  08-11-2016 1 

我很感激你的想法!

+1

可以嘗試,並解釋你對你如何對數據進行分組的邏輯? – DForck42

+0

你正在使用哪個版本的sql server? –

+0

@Prdp SQL server 2014 management studio –

回答

5

通常稱爲組和島問題。這裏有一個方法可以做到這一點

;WITH data 
    AS (SELECT *,Lag(Value, 1)OVER(ORDER BY Dates) [pVal] 
     FROM (VALUES ('08-01-2016',1), 
        ('08-02-2016',1), 
        ('08-03-2016',1), 
        ('08-04-2016',1), 
        ('08-05-2016',1), 
        ('08-06-2016',2), 
        ('08-07-2016',2), 
        ('08-08-2016',2), 
        ('08-09-2016',2.5), 
        ('08-10-2016',1), 
        ('08-11-2016',1)) tc (Dates, Value)), 
    intr 
    AS (SELECT Dates, 
       Value, 
       Sum(Iif(pVal = Value, 0, 1)) OVER(ORDER BY Dates) AS [Counter] 
     FROM data) 
SELECT Min(Dates) AS Dates_from, 
     Max(Dates) AS Dates_to, 
     Value 
FROM intr 
GROUP BY [Counter], 
      Value 
+0

非常感謝! –

2

累計和/滯後方法是一種方法。在這種情況下,更簡單的方法是:

select min(date) as date_from, max(date) as date_to, value 
from (select t.*, 
      dateadd(day, - row_number() over (partition by value order by date),date) as grp 
     from t 
    ) t 
group by value, grp; 

這使用觀察日期連續且沒有間隙。因此,從日期減去一個序列將產生一個常數 - 當value s是相同的。

+0

這隻適用於1和2.沒有在2.5的作品 – Mansoor

+0

這是不是適用於「2.5」? –

+0

@ Gordon Linoff - 對不起,我聲明數值數據類型爲INT現在我聲明值數據類型爲十進制然後check.It工作正常。 – Mansoor

1

下面是一個例子:

DECLARE @T TABLE (
    [Date] DATE, 
    [Value] DECIMAL(9,2) 
) 

INSERT @T VALUES 
('08-01-2016', 1), 
('08-02-2016', 1), 
('08-03-2016', 1), 
('08-04-2016', 1), 
('08-05-2016', 1), 
('08-06-2016', 2), 
('08-07-2016', 2), 
('08-08-2016', 2), 
('08-09-2016', 2.5), 
('08-10-2016', 1), 
('08-11-2016', 1) 

SELECT * FROM @T 

SELECT A.[Date] StartDate, B.[Date] EndDate, A.[Value] FROM (
    SELECT A.*, ROW_NUMBER() OVER (ORDER BY A.[Date], A.[Value]) O FROM @T A 
    LEFT JOIN @T B ON B.[Value] = A.[Value] AND B.[Date] = DATEADD(d, -1, A.[Date]) 
    WHERE B.[Date] IS NULL 
) A 
JOIN (
    SELECT A.*, ROW_NUMBER() OVER (ORDER BY A.[Date], A.[Value]) O FROM @T A 
    LEFT JOIN @T B ON B.[Value] = A.[Value] AND B.[Date] = DATEADD(d, 1, A.[Date]) 
    WHERE B.[Date] IS NULL 
) B ON B.O = A.O 
1

Prdp的解決方案是偉大的,但爲了以防萬一,如果有人還在使用SQL Server 2008,其中LAG()和並行數據倉庫(PDW)功能不可用在這裏是一種替代方案:

示例數據:

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL 
    DROP TABLE #Temp; 

CREATE TABLE #Temp([Dates] DATE 
       , [Value] FLOAT); 

INSERT INTO  #Temp([Dates] 
       , [Value]) 
VALUES 
     ('08-01-2016' 
    , 1), 
     ('08-02-2016' 
    , 1), 
     ('08-03-2016' 
    , 1), 
     ('08-04-2016' 
    , 1), 
     ('08-05-2016' 
    , 1), 
     ('08-06-2016' 
    , 2), 
     ('08-07-2016' 
    , 2), 
     ('08-08-2016' 
    , 2), 
     ('08-09-2016' 
    , 2.5), 
     ('08-10-2016' 
    , 1), 
     ('08-11-2016' 
    , 1); 

QUERY:

;WITH Seq 
    AS (SELECT SeqNo = ROW_NUMBER() OVER(ORDER BY [Dates] 
             , [Value]) 
      , t.Dates 
      , t.[Value] 
     FROM #Temp t) 
    SELECT StartDate = MIN([Dates]) 
     , EndDate = MAX([Dates]) 
     , [Value] 
    FROM 
      (SELECT [Value] 
       , [Dates] 
       , SeqNo 
       , rn = SeqNo - ROW_NUMBER() OVER(PARTITION BY [Value] ORDER BY SeqNo) 
      FROM Seq s) a 
    GROUP BY [Value] 
      , rn 
    ORDER BY StartDate; 

結果:

enter image description here