【问题标题】:SQL Collapse DataSQL 折叠数据
【发布时间】:2018-11-20 23:45:10
【问题描述】:

我正在尝试折叠按日期排序的数据。在按人员和类型分组时。

数据存储在 SQL 服务器中,如下所示 -

seq  person  date                 type
---  ------  -------------------  ----
1    1       2018-02-10 08:00:00  1
2    1       2018-02-11 08:00:00  1
3    1       2018-02-12 08:00:00  1
4    1       2018-02-14 16:00:00  1
5    1       2018-02-15 16:00:00  1
6    1       2018-02-16 16:00:00  1
7    1       2018-02-20 08:00:00  2
8    1       2018-02-21 08:00:00  2
9    1       2018-02-22 08:00:00  2
10   1       2018-02-23 08:00:00  1
11   1       2018-02-24 08:00:00  1
12   1       2018-02-25 08:00:00  2
13   2       2018-02-10 08:00:00  1
14   2       2018-02-11 08:00:00  1
15   2       2018-02-12 08:00:00  1
16   2       2018-02-14 16:00:00  3
17   2       2018-02-15 16:00:00  3
18   2       2018-02-16 16:00:00  3

该数据集包含大约 120 万条与上述类似的记录。

我想从中得到的结果是 -

person  start                type
------  -------------------  ----
1       2018-02-10 08:00:00  1
1       2018-02-20 08:00:00  2
1       2018-02-23 08:00:00  1
1       2018-02-25 08:00:00  2
2       2018-02-10 08:00:00  1
2       2018-02-14 16:00:00  3

我通过运行以下查询获得了第一种格式的数据 -

select 
  ROW_NUMBER() OVER (ORDER BY date) AS seq 
  person, 
  date, 
  type, 
from table
group by person, date, type   

我只是不知道如何将最小日期与人员和类型的其他不同值保持一致。

【问题讨论】:

  • 标记您正在使用的 DBMS(即MySQLSQL Server 等)。
  • 我已经添加了标签 sql-server。谢谢推荐。

标签: sql sql-server gaps-and-islands distinct-values


【解决方案1】:

这是一个差距和孤岛问题,因此,您可以使用row_number() 的差异并在分组中使用它们:

select person, min(date) as start, type
from (select *, 
              row_number() over (partition by person order by seq) seq1,
              row_number() over (partition by person, type order by seq) seq2
      from table
     ) t
group by person, type, (seq1 - seq2)
order by person, start;

【讨论】:

  • 我在这个查询中看到了一些奇怪的事情。在一个示例中:2018-12-30 06:30:00 的类型为 6,但结果显示类型为 1。我还看到当时间不同时会创建不同的记录,因此这些记录彼此跟随- 1373 2009-02-24 08:00:00 1 1373 2009-03-10 18:00:00 1
  • @stats。 . .可能在group by 子句中也需要type
【解决方案2】:

使用行号差异的正确解决方案是:

select person, type, min(date) as start
from (select t.*, 
             row_number() over (partition by person order by seq) as seqnum_p,
             row_number() over (partition by person, type order by seq) as seqnum_pt
      from t
     ) t
group by person, type, (seqnum_p - seqnum_pt)
order by person, start;

type 需要包含在GROUP BY 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2013-12-13
    • 2023-03-29
    • 1970-01-01
    • 2021-01-15
    • 2016-12-22
    相关资源
    最近更新 更多