【问题标题】:SQL - Find the min(date) since a category has its most recent valueSQL - 查找最小(日期),因为类别具有最新值
【发布时间】:2022-01-16 16:06:53
【问题描述】:

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

假设我有下表:

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

该表由month 分区。 这是我的表格的一部分,其中包含多个contract_ids。 我试图找出每个contract_id,因为它有最新的tariff_id,自从它有product_category_id='small'(如果它没有小产品类别,那么值应该是@ 987654328@).

结果将写入每个月更新的表格中。

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

contract_id same_tariff_id_since product_category_small_since
123456 01.06.2021 NULL

我正在使用 Hive。 到目前为止,我只能为same_tariff_id_since想出这个解决方案:

问题是它给了我绝对的min(date) tariff_id 而不是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

提前致谢。

【问题讨论】:

    标签: sql database hive impala


    【解决方案1】:

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

    这是完成任务的代码。这仅返回每个合同的最新版本以及您在最新结果表中描述的特定列。这是针对 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

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

    【讨论】:

    • 您好,感谢您的回答。它工作正常,但我需要对其进行一些更改,以便每个contract_id 只输出一行,如我在上面的示例结果中所示。
    猜你喜欢
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    • 2022-01-20
    • 2015-08-26
    • 1970-01-01
    • 2012-09-05
    相关资源
    最近更新 更多