SQL,分析函数,rownumber

时间:2018-04-03 06:34:52

标签: sql oracle window-functions gaps-and-islands

我需要在SQL中获得相同的rownumber或数值,以便将符合条件的值分组,如下例所示:

如果我们有相同的代理名称,并且当前行和前一行值之间的时间差异小于按名称应用分区并按时间排序后的06:00小时 然后添加相同的rownumber,否则增加它。

行数据和rownumber输出的示例:

person  date_time   rownumber
A   01/04/2018 10:00    1
A   01/04/2018 13:00    1
A   01/04/2018 14:00    1
A   01/04/2018 15:00    1
A   01/04/2018 23:00    2
A   02/04/2018 03:00    2
A   02/04/2018 12:00    3
A   02/04/2018 16:00    3
B   01/04/2018 17:00    4
B   01/04/2018 20:30    4
C   01/04/2018 18:00    5
C   01/04/2018 22:00    5

1 个答案:

答案 0 :(得分:4)

您可以使用LAG和SUM分析函数的组合来完成此操作,如下所示:

WITH your_table AS (SELECT 'A' person, to_date('01/04/2018 10', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('01/04/2018 13', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('01/04/2018 14', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('01/04/2018 15', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('01/04/2018 23', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('02/04/2018 03', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('02/04/2018 12', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'A' person, to_date('02/04/2018 16', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'B' person, to_date('01/04/2018 17', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'B' person, to_date('01/04/2018 20', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'C' person, to_date('01/04/2018 18', 'dd/mm/yyyy hh24') date_time FROM dual UNION ALL
                    SELECT 'C' person, to_date('01/04/2018 22', 'dd/mm/yyyy hh24') date_time FROM dual)
SELECT person,
       date_time,
       SUM(period_change) OVER (ORDER BY person, date_time) rownumber
FROM   (SELECT person,
               date_time,
               CASE WHEN date_time - LAG(date_time, 1, date_time - 7/24) OVER (PARTITION BY person ORDER BY date_time) > 6/24 THEN 1 ELSE 0 END period_change
        FROM   your_table);

PERSON DATE_TIME    ROWNUMBER
------ ----------- ----------
A      01/04/2018           1
A      01/04/2018           1
A      01/04/2018           1
A      01/04/2018           1
A      01/04/2018           2
A      02/04/2018           2
A      02/04/2018           3
A      02/04/2018           3
B      01/04/2018           4
B      01/04/2018           4
C      01/04/2018           5
C      01/04/2018           5

这可以通过在触发新组时在附加列中放置1来实现。

完成后,您可以在该列上执行运行总和。这意味着在每次更改组后,后续行将被分配相同的编号,直到下一组更改。

N.B。正如Peter Lang在下面的评论中所建议的那样,您可能更愿意更改生成" period_change"专栏:

CASE WHEN date_time - LAG(date_time) OVER (PARTITION BY person ORDER BY date_time) < 6/24 THEN 0 ELSE 1 END