(提交以下内容既是尝试共享最佳做法,也是要求获得更多意见……)
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的响应 :由于我需要的是最大日期的汇率,因此我还需要在该子查询中选择汇率,这意味着需要将其分组,而我最终会在同一地方;加入太多。
还有其他建议和/或解决方法吗?
答案 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