如何为一个列选择不同的列而在另一列中选择任何列?


29

我需要查询一个SQL数据库以查找一列的所有不同值,并且需要另一列的任意值。例如,考虑具有两列的下表,键和值:

key     value
===     =====
one     test
one     another
one     value
two     goes
two     here
two     also
three   example

我希望从每个不同的键中取回一个任意选择的示例行,也许可以得到以下三行:

key     value
===     =====
one     test
two     goes
three   example

如何在SQL中制定这样的查询?


2
哪个DBMS(Oracle,SQL-Server,DB2,MySQL,Postgres)?
ypercubeᵀᴹ

1
这是一个专有系统。
WilliamKF 2012年

Answers:


33

最容易编写的查询是针对MySQL(没有严格的ANSI设置)的查询。它使用非标准构造:

SELECT key, value
FROM tableX
GROUP BY key ;

在严格的设置和ONLY_FULL_GROUP_BY默认设置的最新版本(5.7和8.0+)中,您可以使用ANY_VALUE()5.7中添加的功能:

SELECT key, ANY_VALUE(value) AS value
FROM tableX
GROUP BY key ;

对于其他具有窗口功能的DBMS(例如Postgres,SQL-Server,Oracle,DB2),您可以像这样使用它们。好处是您还可以选择结果中的其他列(key和之外value):

SELECT key, value
FROM tableX
    ( SELECT key, value,
             ROW_NUMBER() OVER (PARTITION BY key 
                                ORDER BY whatever)     --- ORDER BY NULL
               AS rn                                   --- for example
      FROM tableX
    ) tmp 
WHERE rn = 1 ;

对于上述版本的较早版本以及任何其他DBMS,几乎在任何地方都可以使用通用方法。一个缺点是您无法使用这种方法选择其他列。另一个是聚合函数,例如MIN()MAX()某些DBMS中的某些数据类型(例如位,文本,blob)不适用于这些数据类型:

SELECT key, MIN(value) AS value
FROM tableX
GROUP BY key ;

PostgreSQL有一个特殊的非标准DISTINCT ON运算符也可以使用。可选的ORDER BY是从每个组中选择应该选择的行:

SELECT DISTINCT ON (key) key, value
FROM tableX
-- ORDER BY key, <some_other_expressions> ;

2
@WilliamKF如果通过“任意选择”的意思是“随机选择”,则只需ORDER BY whatever将对ypercube的查询替换为对函数的调用即可将结果随机化。
Leigh Riffel 2012年

1
@LeighRiffel不必是随机的,任何选择,就像遇到的第一个一样简单就可以了。
WilliamKF 2012年

3

对于MS-SQl服务器:

;with FinalDataset as
(
    select *,
        row_number() over(partition by key order by value) as rownum
    from YourOriginalTable
)
select
   key,
   value
from FinalDataset 
where rownum = 1

同样,第二个结果集可能具有rownum = 2


2

与接受的答案类似,但是可以使用array_agg()代替min()或max()

SELECT key, (array_agg(value))[1] AS value
FROM tableX
GROUP BY key ;

您可以选择对数组中的值进行排序以选择其中的最大或最小值:

SELECT key, (array_agg(value) ORDER BY value DESC)[1] AS value
FROM tableX
GROUP BY key ;

(在PostgreSQL上检查)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.