了解PARTITION BY,是否有更好的方法来获得相同的答案?

时间:2013-01-07 15:35:09

标签: sql oracle

我正在重建的查询中有以下代码段:

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。返回所有这些记录只是为了后来立即丢弃它们似乎有点浪费

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()