SQL - 查找最小(日期),因为类别具有其最新值

SQL - Find the min(date) since a category has its most recent value

我需要一些帮助来解决这个问题。

假设我有以下 table:

contract_id tariff_id product_category date (DD.MM.YYYY) month (YYYYMM)
123456 ABC small 01.01.2021 202101
123456 ABC medium 01.02.2021 202102
123456 DEF small 01.03.2021 202103
123456 DEF small 01.04.2021 202104
123456 ABC big 01.05.2021 202105
123456 DEF small 01.06.2021 202106
123456 DEF medium 02.06.2021 202106
123456 DEF medium 01.07.2021 202107

table 被 month 分割。 这是我的 table 的一部分,包含多个 contract_id。 我试图找出每个 contract_id,因为它有最新的 tariff_id 以及它有 product_category_id='small' 的时间(如果它没有 small 作为产品类别,该值应为 Null).

结果将写入 table,每月更新一次。

所以对于上面的 table,我的最新结果应该是这样的:

contract_id same_tariff_id_since product_category_small_since
123456 01.06.2021 NULL

我正在使用 Hive。 到目前为止,我只能为 same_tariff_id_since:

想出这个解决方案

问题是它给了我 tariff_id 的绝对 min(date) 而不是 min(date) 自最近的 tariff_id.

我认为 product_category_small_since 的代码大体上具有相同的逻辑。

我当前的代码是:

SELECT q2.contract_id
     , q3.tariff_id
     , q2.date
FROM (
SELECT contract_id
     , max(date_2) AS date
FROM (
SELECT contract_id
     , date
     , min(date) OVER (PARTITION BY tariff_id ORDER BY date) AS date_2
FROM given_table 
)q1
WHERE date=date_2
GROUP BY contract_id
)q2
JOIN given_table AS q3
ON q2.contract_id=q3.contract_id
AND q2.date=q3.date

提前致谢。

解决此类查询的一种方法是对要跟踪的序列进行分组。对于 tariff_id 序列分组,每次给定合同 ID 的关税 ID 更改时,您都需要一个新的“序列分组 ID”。由于 product_category 可以独立更改,因此您还需要为该更改做一个序列分组 ID。

这是完成任务的代码。这只是 returns 每个合约的最新版本以及您在最新结果中描述的特定栏目 table。这是针对 PostgreSQL 9.6 完成的,但可以修改语法和数据类型以与 Hive 兼容。

https://www.db-fiddle.com/f/qSk3Mb9Xfp1NDo5VeA1qHh/8

  select q2.contract_id
    , to_char(min(q2."date (DD.MM.YYYY)") 
        over (partition by q2.contract_id, q2.contract_tariff_sequence_id), 'DD.MM.YYYY') as same_tariff_id_since
    , to_char(min(case when q2.product_category = 'small' then q2."date (DD.MM.YYYY)" else null end) 
        over (partition by q2.contract_id, q2.contract_product_category_sequence_id), 'DD.MM.YYYY') as product_category_small_since
  from(
      select q1.*
      , sum(case when q1.tariff_id = q1.prior_tariff_id then 0 else 1 end) 
          over (partition by q1.contract_id order by q1."date (DD.MM.YYYY)" rows unbounded preceding) as contract_tariff_sequence_id
      , sum(case when q1.product_category = q1.prior_product_category then 0 else 1 end) 
          over (partition by q1.contract_id order by q1."date (DD.MM.YYYY)" rows unbounded preceding) as contract_product_category_sequence_id
    from (
        select *
          , lag(tariff_id) over (partition by contract_id order by "date (DD.MM.YYYY)") as prior_tariff_id
          , lag(product_category) over (partition by contract_id order by "date (DD.MM.YYYY)") as prior_product_category
          , row_number() over (partition by contract_id order by "date (DD.MM.YYYY)" desc) latest_record_per_contract
        from contract_tariffs 
    ) q1
  ) q2
  where latest_record_per_contract = 1

如果您想查看所有的行和列,以便您可以检查它如何与序列分组 ID 等一起使用,您可以稍微修改外部查询:

https://www.db-fiddle.com/f/qSk3Mb9Xfp1NDo5VeA1qHh/10

如果这对您有用,请标记为正确答案。