SQL SELECT列上具有MAX值的行,并返回所有列

时间:2014-03-21 16:02:38

标签: sql oracle greatest-n-per-group

好的,我有这张桌子:

+----+--------------+------------------+----------+
| id | business_key | other columns... | creation |
+----+--------------+------------------+----------+
|  1 |            1 |              ... | 01/01/14 |
|  2 |            1 |              ... | 12/02/14 |
|  3 |            1 |              ... | 13/03/14 | <--
|  4 |            2 |              ... | 01/01/14 |
|  5 |            2 |              ... | 12/02/14 | <--
|  6 |            8 |              ... | 01/01/14 | <--
|  7 |           10 |              ... | 01/01/14 |
|  8 |           10 |              ... | 12/02/14 |
|  9 |           10 |              ... | 13/03/14 |
| 10 |           10 |              ... | 13/03/14 | <--
+----+--------------+------------------+----------+

对于每个业务键,我想返回最近的行,为此我有&#34;创建&#34;栏(见上面的箭头)。简单的答案是:

SELECT business_key, MAX(creation) FROM mytable GROUP BY business_key;

问题是,我需要返回所有列。然后我在StackOverflow上了解了标签的存在,我找到了这个主题:SQL Select only rows with Max Value on a Column。最好的答案很棒,并提供此请求:

SELECT mt1.*
FROM mytable mt1
LEFT OUTER JOIN mytable mt2
ON (mt1.business_key = mt2.business_key AND mt1.creation < mt2.creation)
WHERE mt2.business_key IS NULL;

可悲的是,它不起作用,因为我的情况有点棘手:如果你查看我的表格的第9行和第10行,你会发现它们具有相同的商业密钥和相同的创建日期。虽然在我的应用程序中应该避免这种情况,但如果发生这种情况,我仍然需要处理它。

根据上面的最后一个请求,我将得到这个:

+----+--------------+------------------+----------+
| id | business_key | other columns... | creation |
+----+--------------+------------------+----------+
|  3 |            1 |              ... | 13/03/14 |
|  5 |            2 |              ... | 12/02/14 |
|  6 |            8 |              ... | 01/01/14 |
|  9 |           10 |              ... | 13/03/14 | <--
| 10 |           10 |              ... | 13/03/14 | <--
+----+--------------+------------------+----------+

虽然我想要这个:

+----+--------------+------------------+----------+
| id | business_key | other columns... | creation |
+----+--------------+------------------+----------+
|  3 |            1 |              ... | 13/03/14 |
|  5 |            2 |              ... | 12/02/14 |
|  6 |            8 |              ... | 01/01/14 |
| 10 |           10 |              ... | 13/03/14 | <--
+----+--------------+------------------+----------+

我知道在类似&#34; id&#34;这样的技术专栏上想要MAX()是一个糟糕的选择,但现在它是我防止重复的唯一方法业务密钥和创建日期是相同的。问题是,我不知道该怎么做。任何的想法 ?请记住它必须返回所有列(并且我们有很多列,因此需要SELECT *)。

非常感谢。

1 个答案:

答案 0 :(得分:3)

首先想到的是id似乎与日期一起递增,所以只需使用它:

SELECT mt1.*
FROM mytable mt1 LEFT OUTER JOIN
     mytable mt2
     ON mt1.business_key = mt2.business_key AND mt2.id > mt1.id
WHERE mt2.business_key IS NULL;

你仍然可以用两列来做同样的想法:

SELECT mt1.*
FROM mytable mt1 LEFT OUTER JOIN
     mytable mt2
     ON mt1.business_key = mt2.business_key AND
        (mt2.creation > mt1.creation OR
         mt2.creation = mt1.creation AND
         mt2.id > mt1.id
        )
WHERE mt2.business_key IS NULL;