SQL服务器就像Group By任务一样

时间:2016-11-22 15:08:38

标签: sql sql-server sql-server-2014

我有一个带有SQL server的表,如下所示,

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

感谢您的想法!

4 个答案:

答案 0 :(得分: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 

答案 1 :(得分: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相同时,从日期中减去序列将产生一个常量。

答案 2 :(得分:1)

以下是一个例子:

set

答案 3 :(得分: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