无法使用LIMIT 1

时间:2019-10-16 19:43:05

标签: snowflake-data-warehouse

(提交以下内容既是尝试共享最佳做法,也是要求获得更多意见……)


Q: 我需要运行一个查询来获取交易的汇率。根据交易的日期,我需要汇率历史记录表中的最新汇率,该汇率的开始生效日期小于该交易的日期。

基本上是:

SELECT  t.Amount, t.TrxDate, t.Currency, ex.ExchangeRate
FROM Transactions t
LEFT JOIN LATERAL (
    SELECT ExchangeRate 
    FROM RateHistory h
    WHERE t.TrxDate <= h.EffectiveDate AND t.Currency = h.Currency ORDER BY EffectiveDate DESC 
    LIMIT 1) ex

问题来自LIMIT1。我不能让此子查询返回多行,我只需要最新汇率即可。使用LIMIT 1或尝试使用ROW_NUMBER()和条件连接都将导致相同的“不支持的子查询”错误。

有人有什么建议吗?该查询在其他地方效果很好,但在Snowflake中效果不佳。

这是实际的查询。最后一个子查询就是问题。

SELECT
        'SG' AS Region,
        CAST(gl.acct_no AS NUMERIC(12,6)) AS acct_no, 
        gl.trx_date, 
        source, 
        gl.reference, 
        doc_no, 
        gl.amount, 
        for_amt,
        reference2,
        gl.reg_int_id, 
        gl.reg_seq_no, 
        gl.curr_id AS gl_curr_id, 
        c.curr_id AS chart_curr_id,
        z.reference AS reference3,
        z.dist_dt,
        cur.cur_desc,
        ex.exchng_rate 
FROM            gltrx  gl
JOIN            chart c ON ROUND(c.acct_no,6) = ROUND(gl.acct_no,6)
LEFT OUTER JOIN currencies cur ON gl.curr_id = cur.curr_id
LEFT JOIN LATERAL (SELECT MAX(ap.reference) AS reference, MIN(aph.dist_dt) AS dist_dt
        FROM    apdist ap
        LEFT OUTER JOIN aphist aph ON ap.voucher_no = aph.voucher_no
        WHERE ap.reg_int_id = gl.reg_int_id AND ap.reg_seq_no = gl.reg_seq_no) z                     
LEFT JOIN LATERAL (SELECT Exchng_rate
        FROM    Curr_hist 
        WHERE Curr_Id = gl.curr_id
        AND Exchng_Dt <= gl.trx_date 
        ORDER BY exchng_dt DESC 
        LIMIT 1) ex

建议1: 尝试在以下查询中成功返回一行,emp表和dept表均具有两行。

SELECT * FROM EMP WHERE DEPTNO = (SELECT DEPTNO FROM DEPT LIMIT 1)

因此我们可以在子查询中使用LIMIT,LIMIT没有问题,问题出在其他地方。

尝试将查询分解成多个部分,然后分别运行每个部分,然后将它们一个接一个地进行分析。

对建议1的响应: 该子查询有效,但是问题是LEFT JOIN LATERAL。我已经尝试过不带LIMIT 1的查询,并且工作正常……除了很明显它返回的结果太多。


建议2: 我们使用LATERAL的任何特定原因?

尝试使用with子句编写子查询,然后再加入。

对建议2的响应: 使用LATERAL,因为我需要从子查询中获取一条记录,才能将其连接到事务表中的每条记录。 LATERAL允许条件聚合来实现。我不确定使用WITH子句的意思。您是否建议CTE?


建议3: 也许您可以尝试删除LATERAL,也可以使用MAX函数而不是对子查询进行排序并获得限制,因为从本质上讲,您需要指定日期之后的最新费率,但是截止日期之前最多可以给您。

SELECT t.Amount, t.TrxDate, t.Currency, ex.ExchangeRate
FROM Transactions t
LEFT JOIN (
SELECT MAX(h.EffectiveDate ), h.Currency
FROM RateHistory h
WHERE t.TrxDate <= h.EffectiveDate
AND t.Currency = h.Currency
GROUP BY h.Currency
) ex

对建议3的响应 :由于我需要的是最大日期的汇率,因此我还需要在该子查询中选择汇率,这意味着需要将其分组,而我最终会在同一地方;加入太多。


还有其他建议和/或解决方法吗?

2 个答案:

答案 0 :(得分:1)

因此,我将第一个LATERAL移到了CTE,这可能不是问题所在。 第二个LATERAL需要每行gl.tx_date,因此,如果您仅在其中保留LEFT JOIN(这让很多行都可以),然后使用ROW_NUMBER()来实现{{1} }。这使我认为这会很慢,但应该可以。

LIMIT 1

答案 1 :(得分:1)

使用窗口函数来确保仅获得一行?

(SELECT Exchng_rate,
        RANK() OVER (ORDER BY exchng_dt DESC) as order 
        FROM    Curr_hist 
        WHERE Curr_Id = gl.curr_id
        AND Exchng_Dt <= gl.trx_date 
        ) 
where order=1