我有一张这样的桌子:
ID | Val | Kind
----------------------
1 | 1337 | 2
2 | 1337 | 1
3 | 3 | 4
4 | 3 | 4
我想做一个SELECT
只返回每个的第一行Val
,按Kind
.
样本输出:
ID | Val | Kind
----------------------
2 | 1337 | 1
3 | 3 | 4
如何构建此查询?
使用公用表表达式(CTE) 和像ROW_NUMBER这样的窗口/排名/分区函数。
此查询将创建一个名为 ORDERED 的内存表,并添加一个附加列 rn,它是从 1 到 N 的数字序列。PARTITION BY表示每次 Val 的值更改并且我们想要排序时它应该从 1 重新开始按 Kind 的最小值排列。
上述方法应该适用于任何已实现 ROW_NUMBER() 函数的 RDBMS。Oracle 有一些优雅的功能,如mik 的答案中所表达的,通常会产生比这个答案更好的性能。
此解决方案也使用
keep
, 但val
也kind
可以简单地为每个组计算而无需子查询:dbfiddle在这里
KEEP...FIRST 和 KEEP...LAST 是 Oracle 特有的聚合功能——您可以在 Oracle 文档或ORACLE_BASE 上阅读有关内容:
bilinkc 的解决方案效果很好,但我想我也会把我的也扔掉。它的成本相同,但可能更快(或更慢,我没有测试过)。不同之处在于它使用 First_Value 而不是 Row_Number。由于我们只对第一个值感兴趣,所以在我看来它更直接。
测试数据。
如果您愿意,这里是 CTE 等价物。
您可以使用从每个组
keep
中选择一个:id
dbfiddle在这里
select * from (select t1.*,ROW_NUMBER() OVER (PARTITION BY Val ORDER BY Val desc) as seqnum from tablename t1) where seqnum=1;