如何使用窗口函数来确定何时在Hive或Postgres中执行不同的任务?

时间:2018-02-03 15:01:57

标签: sql postgresql hive window-functions

我是SQL的新手,需要能够在Hive和Postgres中解决以下问题。

数据

我有一些数据显示每人不同的优先排序任务的开始日期和结束日期:

   person      task_key start_day end_day
1    Kate             A         1       5
2    Kate             B         1       5
3    Adam             A         1       5
4    Adam             B         2       5
5     Eve             A         2       5
6     Eve             B         1       5
7   Jason             A         1       5
8   Jason             B         4       5
9   Jason             C         3       5
10  Jason             D         5       5
11  Jason             E         4       5

注意:订购任务键,以便更高的字母具有更高的优先级。

问题

我需要弄清楚每个人每天应该做的工作,条件是:

  1. 较高的字母任务优先于较低的字母任务。
  2. 如果较高的字母任务与较低字母任务的任何部分重叠,则较低的字母任务将设置为NA(表示该人不应该对其进行操作)。
  3. 简化 在实际数据中,end_day在原始表中始终为5,即只有start_day变化但end_day是常量。这意味着我所需的输出将与原始表具有相同的行数:)

    输出

    这是我需要的那种输出(杰森更能代表我拥有的数据,可以覆盖90天的超过100个任务):

       person    task_key start_day end_day valid_from valid_to
    1    Kate           A         1       5         NA       NA
    2    Kate           B         1       5          1        5
    3    Adam           A         1       5          1        2
    4    Adam           B         2       5          2        5
    5     Eve           A         2       5         NA       NA
    6     Eve           B         1       5          1        5
    7   Jason           A         1       5          1        3
    8   Jason           B         4       5         NA       NA
    9   Jason           C         3       5          3        4
    10  Jason           D         5       5         NA       NA
    11  Jason           E         4       5          4        5
    

    感谢您提前抽出时间。

    P.S。类似的问题我在R:How to use a window function to determine when to perform different tasks?

    中提出了问题

1 个答案:

答案 0 :(得分:2)

Postgres中的解决方案相当简单,因为它支持generate_series()。首先,为表中的每一行每天爆炸一行数据:

select d.*, gs.dy
from data d, lateral
     generate_series(start_day, end_day) gs(dy);

然后,聚合以获取每天的任务:

select d.person, d.dy, max(d.task_key) as task_key
from (select d.*, gs.dy
      from data d, lateral
           generate_series(start_day, end_day) gs(dy)
     ) d
group by d.person, d.dy;

然后你可以重新聚合,但这很棘手,因为你可能有"分裂"原始行(请参阅我的评论)。这回答了您关于在哪一天执行哪项任务的问题。

您可以使用数字/计数表在没有横向连接或generate_series()的情况下完成所有这些操作。