我正在重建的查询中有以下代码段:
LEFT JOIN (SELECT ACCOUNT_ID, LETTER_TYPE, LETTER_DATE, LETTER_ID
FROM (SELECT T1.ACCOUNT_ID, T2.LETTER_TYPE, T1.LETTER_DATE, T1.LETTER_ID,
DENSE_RANK() OVER (PARTITION BY T1.ACCOUNT_ID, T2.LETTER_TYPE
ORDER BY T1.LETTER_DATE DESC) AS RANK1
FROM tableOne T1
INNER JOIN tableTwo T2 ON T1.LETTER_ID = T2.LETTERID)
WHERE RANK1 = 1)
之前我还没有真正处理过DENSE_RANK()
或PARTITION BY
,但根据我的研究,这个案例会转换为“按ACCOUND_ID和LETTER_DATE降序排序这组记录”然后外部的SELECT抓取只有RANK = 1的那些。所以它基本上试图找到为每个帐户发送的最新LETTER_ID。
我的问题是: A。这是一个准确的翻译吗?和 B。有没有办法重写/重构这个查询,以便它不必像这样嵌套?
我在 B。中的含义是它首先返回所有LETTER_ID,然后过滤到WHERE RANK1 = 1
。返回所有这些记录只是为了后来立即丢弃它们似乎有点浪费
答案 0 :(得分:2)
您可以将查询重写为:
LEFT JOIN (select t1.account_id, t2.letter_type, MAX(t1.letter_date) as MaxDate
from tableOne t1 join tableTwo t2 on T1.LETTER_ID = T2.LETTERID
) maxt left outer join
(select T1.ACCOUNT_ID, T2.LETTER_TYPE, T1.LETTER_DATE, T1.LETTER_ID
from tableOne t1 join tableTwo t2 on T1.LETTER_ID = T2.LETTERID
) t
on t.account_id = tmax.account_id and t.letter_type = tmax.letter_type and
t.letter_date = tmax.maxdate
但是,我建议你窗口/分析函数是非常强大的SQL补充,所以你应该学习如何使用它们。
但在这种情况下有一个问题。如果最近的letter_date上有多个字母,那么您的查询(以及此查询)将返回所有字母。也许你的意图是只返回其中一个。在这种情况下,您可以使用row_number()
代替dense_rank()
。