【问题标题】:How do I group on continuous ranges如何在连续范围内分组
【发布时间】:2011-08-05 11:23:07
【问题描述】:

我知道一些基本的 SQL,但这个超出了我的范围。我看了高低,但没有骰子。我需要查看以下数据,我可以在应用层代码中做到这一点。但不幸的是,对于这个特殊的,代码必须放在数据层中。

我正在使用 T-SQL。

表格

Date      Crew       DayType
01-02-11  John Doe  SEA  
02-02-11  John Doe  SEA  
03-02-11  John Doe  SEA  
04-02-11  John Doe  HOME  
05-02-11  John Doe  HOME  
06-02-11  John Doe  SEA 

我需要这样的视图

DateFrom  DateTo    Name      DayType
01-02-11  03-02-11  John Doe  SEA
04-02-11  05-02-11  John Doe  HOME
06-02-11  06-02-11  John Doe  SEA

不幸的是,应用层需要基表以显示格式。这可以在查询中执行吗?

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql gaps-and-islands


    【解决方案1】:
    WITH    q AS
            (
            SELECT  *,
                    ROW_NUMBER() OVER (PARTITION BY crew, dayType ORDER BY [date]) AS rnd,
                    ROW_NUMBER() OVER (PARTITION BY crew ORDER BY [date]) AS rn
            FROM    mytable
            )
    SELECT  MIN([date]), MAX([date]), crew AS name, dayType
    FROM    q
    GROUP BY
            crew, dayType, rnd - rn
    

    您可能会对这篇文章感兴趣:

    【讨论】:

    • +1,一如既往的好。您是否检查过 ROW_NUMBER 方法在较大的集合上是否比递归方法更快?
    • +1 出于兴趣,如果给定日期的船员姓名有多个 Daytypes(即添加 02-02-11,John Doe,Home 到示例 DDL),最好对 rn 使用 DENSE_RANK 还是有更好的方法?
    • 但是(a)数据已经以关系形式存在,(b)所需的视图是关系(c)SQL处理关系数据。为什么要将其转换为文件(完整的记录 ID),然后将其作为文件处理,耗费大量资源?在此Answer 中给出了解决此问题的方法,无需 1970 年风格的记录 ID 或 CTE
    • 带有 ROW_NUMBER() 的派生表,用于驱动 WITH。检查您的 SHOWPLAN。
    • @PerformanceDBA:对不起,我不明白。派生表与文件有什么关系?我应该在计划中找到什么?
    【解决方案2】:
    WITH grouped AS (
      SELECT
        *,
        grp = DATEDIFF(day, 0, Date) -
              ROW_NUMBER() OVER (PARTITION BY Crew, DayType ORDER BY Date)
      FROM @testtable
    )
    SELECT
      DateFrom = MIN(Date),
      DateTo = MAX(Date),
      Name = Crew,
      DayType
    FROM grouped
    GROUP BY Crew, DayType, grp;
    

    基本上,与 Quassnoi 的解决方案相同,但少用一个 ROW_NUMBER 会产生更好的执行计划。

    【讨论】:

    • 使用DATEDIFF(day, 0, Date) 可确保分组时日期是连续的。 IMO 这是一个更好的答案
    【解决方案3】:
    SELECT MIN(Date) AS DateFrom,MAX(Date) AS DateTo, Crew, DayType FROM yourTableName GROUP BY Crew, DayType
    

    【讨论】:

    • 这个答案不只是给出每个 Crew/DayType 组合的最小和最大日期,但没有分成连续的日期范围。
    【解决方案4】:

    类似的东西:

    SELECT Crew, DayType, MIN(Date) AS SomeDate1, MAX(Date) AS SomeDate2 
    FROM Mytable 
    GROUP BY Crew, DayType
    

    【讨论】:

      【解决方案5】:
      Select Min(Date) DateFrom, Max(Date) DateTo, Crew Name,DayType From Mytable Group By Crew,DayType 
      

      试试这个。

      【讨论】:

      • 这只会返回两行。 01-02-11 06-02-11 John Doe SEA04-02-11 05-02-11 John Doe HOME.
      猜你喜欢
      • 2017-01-30
      • 2016-08-18
      • 1970-01-01
      • 1970-01-01
      • 2018-06-06
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多