雪花相关子查询

时间:2021-03-18 20:32:33

标签: sql snowflake-cloud-data-platform

我发现了其他有类似问题的问题,但答案不符合我的需求,我不知道如何调整它们。当然,问题在于 Snowflake 不支持大多数相关子查询,而且我不知道如何在没有子查询的情况下实现我想要做的事情。这是我希望能够做的:

SELECT
   IH.ID
   , (SELECT "DESCRIPTION" 
      FROM DISPUTE_REASON 
      WHERE INVOICE_HEADER_ID = IH.ID 
      ORDER BY CREATED_AT DESC LIMIT 1) DISPUTE_REASON
FROM
   INVOICE_HEADER IH

关键是我需要能够在发票标题 ID 的范围内获取 DISPUTE_REASON 表中最近创建的记录。我尝试使用函数来执行此操作,但出现相同的错误,“无法评估不受支持的子查询类型”。我也尝试将 FIRST_VALUE 与 GROUP BY 一起使用,但它们不能一起玩。

有人能想出一种不使用相关子查询的方法吗?

4 个答案:

答案 0 :(得分:1)

您可以使用 LEFTINVOICE_HEADERDISPUTE_REASONFIRST 窗口函数的 FIRST_VALUE() 连接:

SELECT DISTINCT ih.ID, 
       FIRST_VALUE(dr.DESCRIPTION) OVER (PARTITION BY ih.ID ORDER BY dr.CREATED_AT DESC) DISPUTE_REASON
FROM INVOICE_HEADER ih LEFT JOIN DISPUTE_REASON dr
ON dr.INVOICE_HEADER_ID = ih.ID

答案 1 :(得分:0)

您可以使用 ARRAY_AGG 的变体,同时使用 WITHIN GROUP 进行排序,然后从数组中提取第一个元素:

SELECT
   IH.ID
   , (ARRAY_AGG(DR."DESCRIPTION") within group (ORDER BY CREATED_AT DESC))[0] DISPUTE_REASON
FROM
   INVOICE_HEADER IH
JOIN DISPUTE_REASON DR
ON DR.INVOICE_HEADER_ID = IH.ID 

答案 2 :(得分:0)

我只想使用这样的窗口函数:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: Empty }', src/main.rs:3:39
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Snowflake 也支持横向连接,所以我很惊讶你的版本不起作用。试试这个:

SELECT IH.ID, dr."DESCRIPTION" as DISPUTE_REASON
FROM INVOICE_HEADER IH LEFT JOIN
     (SELECT dr.*,
             ROW_NUMBER() OVER (PARTITION BY dr.INVOICE_HEADER_ID ORDER BY dr.CREATED_AT DESC) as seqnum
      FROM DISPUTE_REASON dr
     ) dr
     ON dr.INVOICE_HEADER_ID = IH.ID AND dr.seqnum = 1;

答案 3 :(得分:0)

forpas 的 first_value 是针对您所陈述问题的最干净的解决方案。 Gordon 的解决方案是您如何解决这个问题,因为您需要该子表中的许多值。

Gordon 的解决方案也可以用 QUALIFY 来编写,从而再次变得更简洁。

SELECT IH.ID
    , dr."DESCRIPTION" as DISPUTE_REASON
FROM INVOICE_HEADER IH 
LEFT JOIN (
    SELECT *
    FROM DISPUTE_REASON 
    QUALIFY ROW_NUMBER() OVER (PARTITION BY INVOICE_HEADER_ID ORDER BY CREATED_AT DESC) = 1
) dr
    ON dr.INVOICE_HEADER_ID = IH.ID;