如何通过SQL选择唯一记录

Yin*_*nan 69 sql database

当我执行"SELECT*FROM table"时,我得到如下结果:

1 item1 data1
2 item1 data2
3 item2 data3
4 item3 data4
Run Code Online (Sandbox Code Playgroud)

如您所见,column2中有重复记录(item1被重复).那我怎么能得到这样的结果:

1 item1 data1
2 item2 data3
3 item3 data4
Run Code Online (Sandbox Code Playgroud)

只有一个记录从副本返回,以及其余的唯一记录.

mja*_*day 85

您可以使用SELECT DISTINCTGROUP BY执行此操作.

SELECT DISTINCT a, c
FROM table_c
Run Code Online (Sandbox Code Playgroud)

要么

SELECT a, b
FROM table_c
GROUP BY a, b
Run Code Online (Sandbox Code Playgroud)

GROUP BY如果你想使用像COUNT()或的一些聚合函数会更有帮助SUM()

SELECT a, b, count(*)
FROM table_c
GROUP BY a, b

SELECT a, b, sum(d)
FROM table_c
GROUP BY a, b
Run Code Online (Sandbox Code Playgroud)

  • 难道答案实际上是错的吗?DISTINCT应用于所有选定的列(至少在DB2上),它们仍将在各个列中返回重复值. (8认同)
  • 是的,“DISTINCT”不会给出所需的结果(至少在 Postgres 上),因为它应用于所有选择列,而不仅仅是本答案中指定的“column1”。 (7认同)
  • 这在 Bigquery 中不起作用 (4认同)

isa*_*pir 33

您可以使用 4 种方法:

  1. 清楚的
  2. 通过...分组
  3. 子查询
  4. 带有 ROW_NUMBER() 的公共表表达式 (CTE)

考虑以下TABLE带有测试数据的示例:

/** Create test table */
CREATE TEMPORARY TABLE dupes(word text, num int, id int);

/** Add test data with duplicates */
INSERT INTO dupes(word, num, id)
VALUES ('aaa', 100, 1)
      ,('bbb', 200, 2)
      ,('ccc', 300, 3)
      ,('bbb', 400, 4)
      ,('bbb', 200, 5)     -- duplicate
      ,('ccc', 300, 6)     -- duplicate
      ,('ddd', 400, 7)
      ,('bbb', 400, 8)     -- duplicate
      ,('aaa', 100, 9)     -- duplicate
      ,('ccc', 300, 10);   -- duplicate
Run Code Online (Sandbox Code Playgroud)

选项 1:选择 DISTINCT

这是最简单直接,但也是最有限的方式:

SELECT DISTINCT word, num 
FROM    dupes
ORDER BY word, num;

/*
word|num|
----|---|
aaa |100|
bbb |200|
bbb |400|
ccc |300|
ddd |400|
*/
Run Code Online (Sandbox Code Playgroud)

选项 2:分组依据

分组允许您添加汇总数据,如min(id)max(id)count(*),等:

SELECT  word, num, min(id), max(id), count(*)
FROM    dupes
GROUP BY word, num
ORDER BY word, num;

/*
word|num|min|max|count|
----|---|---|---|-----|
aaa |100|  1|  9|    2|
bbb |200|  2|  5|    2|
bbb |400|  4|  8|    2|
ccc |300|  3| 10|    3|
ddd |400|  7|  7|    1|
*/
Run Code Online (Sandbox Code Playgroud)

选项 3:子查询

使用子查询,您可以首先识别要忽略的重复行,然后使用以下WHERE NOT IN (subquery)构造在外部查询中过滤掉它们:

/** Find the higher id values of duplicates, distinct only added for clarity */
    SELECT  distinct d2.id
    FROM    dupes d1
        INNER JOIN dupes d2 ON d2.word=d1.word AND d2.num=d1.num
    WHERE d2.id > d1.id

/*
id|
--|
 5|
 6|
 8|
 9|
10|
*/

/** Use the previous query in a subquery to exclude the dupliates with higher id values */
SELECT  *
FROM    dupes
WHERE   id NOT IN (
    SELECT  d2.id
    FROM    dupes d1
        INNER JOIN dupes d2 ON d2.word=d1.word AND d2.num=d1.num
    WHERE d2.id > d1.id
)
ORDER BY word, num;

/*
word|num|id|
----|---|--|
aaa |100| 1|
bbb |200| 2|
bbb |400| 4|
ccc |300| 3|
ddd |400| 7|
*/
Run Code Online (Sandbox Code Playgroud)

选项 4:使用 ROW_NUMBER() 的公共表表达式

在公共表表达式 (CTE) 中,选择 ROW_NUMBER(),按组列分区并按所需顺序排序。然后仅选择具有ROW_NUMBER() = 1以下内容的记录:

WITH CTE AS (
    SELECT  *
           ,row_number() OVER(PARTITION BY word, num ORDER BY id) AS row_num
    FROM    dupes
)
SELECT  word, num, id 
FROM    cte
WHERE   row_num = 1
ORDER BY word, num;

/*
word|num|id|
----|---|--|
aaa |100| 1|
bbb |200| 2|
bbb |400| 4|
ccc |300| 3|
ddd |400| 7|
*/
Run Code Online (Sandbox Code Playgroud)


rah*_*hul 20

如果您只需删除重复项,请使用DISTINCT.GROUP BY应该用于将聚合运算符应用于每个组

GROUP BY v DISTINCT


Bin*_*ati 10

我不确定接受的答案是否有效。postgres 12至少它不起作用。DISTINCT关键字应该应用于查询中的所有列,而不仅仅是应用于写入关键字select旁边的列。DISTINCT因此,基本上,这意味着结果中返回的每一行在查询列的组合方面都是唯一的select。在OP的问题中,下面的两个结果行已经不同,因为它们的column1和column 3具有不同的值。

1 item1 data1
2 item1 data2
Run Code Online (Sandbox Code Playgroud)

现在,要回答这个问题,至少在 中postgres,有一个DISTINCT ON关键字。这将达到OP的要求。

select DISTINCT ON(column2) column1, column3 from Table1;

  • 这是 Postgres 的一个超级方便的功能,感谢您在这个问题的上下文中指出它!它也被捕获为[另一个问题的接受答案](/sf/answers/1184261991/) (2认同)

Dav*_*ker 9

这取决于您要为每个唯一项目返回哪个rown.您的数据似乎表明最小数据值,因此在此实例中为SQL Server.

SELECT item, min(data)
FROM  table
GROUP BY item
Run Code Online (Sandbox Code Playgroud)


小智 6

只需使用内部连接,因为 group by 不会与多个列一起使用,表示不包含在聚合函数中。

SELECT a.*
FROM yourtable a
INNER JOIN 
  (SELECT yourcolumn,
    MIN(id) as id
  FROM yourtable 
  GROUP BY yourcolumn
) AS b
  ON a.yourcolumn= b.yourcolumn
  AND a.id = b.id;
Run Code Online (Sandbox Code Playgroud)