如何通过 SQL 选择唯一记录

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

1 item1 data1
2 item1 data2
3 item2 data3
4 item3 data4

正如您可以看到的那样,column 2中有一些 dup 记录(item1被转储了)。那么我怎样才能得到这样的结果:

1 item1 data1
2 item2 data3
3 item3 data4

只有一条记录从重复记录中返回,同时返回的还有其他唯一记录。

551032 次浏览

使用具有单列和多列名称的 distinct关键字,您可以获得不同的记录:

SELECT DISTINCT column 1, column 2, ...
FROM table_name;

如果您只需要删除重复项,那么使用 DISTINCT。应该使用 GROUP BY对每个组应用聚合运算符

组由 v 不同

它取决于要为每个唯一项返回哪个行。您的数据似乎指示最小数据值,因此在此 SQLServer 实例中。

SELECT item, min(data)
FROM  table
GROUP BY item

我发现,如果由于任何原因不能使用 DISTINCT,那么 GROUP BY 就可以工作。

要获得结果中的所有列,您需要放置以下内容:

SELECT distinct a, Table.* FROM Table

它将把 作为第一列,其余的将是所有的列,按照与您的定义相同的顺序。也就是说,列 将被重复。

SELECT
Eff_st
FROM
(
SELECT
EFF_ST,
ROW_NUMBER() over(PARTITION BY eff_st) XYZ -
FROM
ABC.CODE_DIM
)
WHERE
XYZ = 1
ORDER BY
EFF_STFETCH FIRST 5 row only


只需使用内部连接即可,因为 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;

你可以使用以下四种方法:

  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

选项1: 选择不同

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

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


/*
word|num|
----|---|
aaa |100|
bbb |200|
bbb |400|
ccc |300|
ddd |400|
*/

选项2: GROUP BY

分组允许您添加聚合数据,如 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|
*/

选项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|
*/

选项4: 具有 ROW _ NUMBER ()的公共表表达式

在 Common Table Expression (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|
*/

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

1 item1 data1
2 item1 data2

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

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

我认为人,谁想要操作查询,谁想要写的查询像星号(*)而不是列(s)。如果是这样,那么这个问题对他有帮助。

如何只根据不同的 COLUMN 值选择行