【问题标题】:Compare records and Generate records比较记录并生成记录
【发布时间】:2019-10-16 01:21:38
【问题描述】:

我的要求是按时间顺序排列记录,并按顺序将每条记录与其下一条记录进行比较。如果第二条记录与与任何字段有关的前一条记录(按 asc 顺序)不同并且该记录是活动的(即标志 = 'F'),则通过生成第二条记录的 eff_date = eff_dt 来拆分第二条记录记录 - 1 天。如果下一条记录是非活动的(即标志 = 'C' 则只输出这条记录而不需要拆分和创建新记录 继续对所有记录进行此比较。

例如,

product | eff_dt | store | region | type
12345 | 18/05/2017 | HA | CA | F
12345 | 05/10/2018 | K1 | CA | F
12345 | 01/02/2019 | K1 | CA | F
12345 | 15/07/2019 | AB | GA | C
12345 | 07/09/2019 | BT | MD | F

从上表中,我们首先按时间顺序排列记录。
现在我们将第一条记录与第二条记录进行比较,发现“store”在第二条记录HA -> K1 中发生了变化,并且第二条记录处于活动状态(标志 = F)。因此,输出需要第一条记录和第二条记录,第二条记录将被分成两部分 - 在 (eff_dt - 1) 日创建新记录。
现在当我们将第三条记录与第二条记录进行比较时,我们看到任何字段的值都没有变化,并且该记录处于活动状态,因此该记录将被忽略并且不会被输出。
现在我们将第四条记录与第三条记录进行比较,我们看到它是非活动的 (flag = 'C'),因此,这条记录将按原样输出,但不会像我们在第一个场景中那样生成新记录。
最后发现第5条记录是商品关闭后的第一个Active记录(在第4条记录中),因此也会输出但不会有新记录已创建。

预期的输出将是:

product | eff_dt | store | region | type
12345 | 18/05/2017 | HA | CA | F      <<--- output
12345 | 04/10/2017 | HA | CA | F      <<--- new record generated with (eff_dt - 1)
12345 | 05/10/2018 | K1 | CA | F      <<--- output as-is
                                           <<--- record not output since no change in values
12345 | 15/07/2019 | AB | GA | C      <<--- record has changes but also Inactive. Hence, output as-is and new record generation not required
12345 | 07/09/2019 | BT | MD | F      <<--- record output since this indicates product is reopened and is active again. No new record required.

任何人都可以帮助解决上述逻辑以及如何通过使用 eff_dt - 1 创建新记录来拆分记录。 如果需要更多信息/澄清,请告诉我

【问题讨论】:

  • 每行有六个值,但只有五个列标题。

标签: sql apache-spark-sql pyspark-sql


【解决方案1】:

嗯。我将此解释为带有一些曲折的间隙和孤岛问题。我不会将“结束”值放在不同的行上,而是将生效日期和结束日期放在一行上:

select product, store, region, type,
       min(eff_dt),
       date_add(lead(eff_dt) over (partition by product order by min(eff_dt), -1) as
from (select t.*,
             row_number() over (partition by product order by eff_dt) as seqnum_p,
             row_number() over (partition by product, store, region, type order by eff_dt) as seqnum_psrt
      from t
     ) t
group by product, store, region, type, (seqnum - seqnum_psrt);

如果你想在不同的行上使用这个,你可以使用union all:

select product, store, region, type, eff_dt
from (select t.*,
             lag(eff_dt) over (partition by product, store, region, type order by eff_dt) as prev_psrt_date,
             lag(eff_dt) over (partition by product order by eff_dt) as prev_date
      from t
     ) t
where prev_date is null or prev_date <> prev_psrt_date
union all
select product, store, region, type,
       date_add(next_date, 1)
from (select t.*,
             lead(eff_dt) over (partition by product, store, region, type order by eff_dt) as next_psrt_date,
             lead(eff_dt) over (partition by product order by eff_dt) as next_date
      from t
     ) t
where next_date <> next_psrt_date or next_psrt_date is null;

此处查找具有相同值的行的技巧是比较上一个/下一个日期——但按数据的不同分区。这比单独比较每一列要简单,而且它也适用于NULL 值。

【讨论】:

  • @marie20 。 . .第一个没有。第二个应该。
  • 此代码是否使用下一条记录 (eff_dt - 1) 创建新行?您的解决方案是否也在考虑活动/非活动状态? type 列是标志:F = activeC = inactive
  • @marie20 。 . .它正在考虑partition by/group by 列表中的任何列。
  • 我找到了一个非常接近我要求的帖子。这可以在 SparkSQL 中以某种方式实现(而不是 pyspark-sql)吗? stackoverflow.com/questions/49047368/…
  • 我将简化要求并创建一个新问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-02
相关资源
最近更新 更多