如何在SQL中选择仅在一个字段上没有重复的记录?

80

我有一个像这样的3列表:

+------------+---------------+-------+  
| Country_id | country_title | State |  
+------------+---------------+-------+    

这个表里有很多记录,其中一些具有state,而其他一些则没有。现在想象一下这些记录:

1 | Canada  | Alberta  
2 |  Canada | British  Columbia  
3 | Canada  | Manitoba  
4 | China   |

我需要没有任何重复的国家名。实际上,我需要它们的idtitle,最好的SQL命令是什么?我在下面的表单中使用了DISTINCT,但我不能达到一个合适的结果。

SELECT DISTINCT title,id FROM tbl_countries ORDER BY title

我的期望结果是这样的:

1, Canada  
4, China

1
你尝试的查询得到了什么结果?与你想要的有何不同? - Mark Byers
我得到了一个包含许多记录的结果集,这些记录都包含加拿大。 - Mohammad Saberi
您想要发生什么变化呢?您能够展示一下您想要的结果集吗?请明确地表达出来。我是指不要只用自己的话语描述您想要的内容。请更新您的问题,以表格形式清晰而精确地展示您得到的确切结果和您想要的确切结果。 - Mark Byers
1
@MarkByers 我需要防止国家名称重复记录,我的意思是我不想显示第二个加拿大,当我已经有一个。 - Mohammad Saberi
1
问题措辞不当 - 你在顶部给出了一组列标题,然后在 SQL 中使用另一组。 - JGFMK
显示剩余3条评论
8个回答

130

试试这个:

SELECT MIN(id) AS id, title
FROM tbl_countries
GROUP BY title

52

DISTINCT 是关键字
对我来说你的查询是正确的

先尝试这样做

SELECT DISTINCT title,id FROM tbl_countries

随后你可以尝试使用 order by。


8
查询结果将只删除“State”列,这并不是OP所需要的;)。 - shA.t
3
这只确保查询结果中的每个元组是唯一的,而不是每个列中的每个值都是唯一的。 - Jodo1992

19

如果要使用 DISTINCT 关键字,您可以像这样使用:

SELECT DISTINCT 
    (SELECT min(ti.Country_id) 
     FROM tbl_countries ti 
     WHERE t.country_title = ti.country_title) As Country_id
    , country_title
FROM 
    tbl_countries t

使用ROW_NUMBER(),您可以像这样使用它:
SELECT 
    Country_id, country_title 
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY country_title ORDER BY Country_id) As rn
    FROM tbl_countries) t
WHERE rn = 1

同时使用 LEFT JOIN,你可以这样做:
SELECT t1.Country_id, t1.country_title
FROM tbl_countries t1
    LEFT OUTER JOIN
    tbl_countries t2 ON t1.country_title = t2.country_title AND t1.Country_id > t2.Country_id
WHERE
    t2.country_title IS NULL

使用 EXISTS,您可以尝试以下操作:

SELECT t1.Country_id, t1.country_title
FROM tbl_countries t1   
WHERE
    NOT EXISTS (SELECT 1 
                FROM tbl_countries t2 
                WHERE t1.country_title = t2.country_title AND t1.Country_id > t2.Country_id)

这可以用于选择一行中的所有数据吗?我发现所有的示例都设置了列,当我使用select *运行时它不起作用。如果这些解决方案对于Select *无效,我不确定是否要继续解决问题。 - Mafster

2

试试这个

SELECT country_id, country_title 
FROM (SELECT country_id, country_title,
CASE
WHEN country_title=LAG(country_title, 1, 0) OVER(ORDER BY country_title) THEN 1
ELSE 0
END AS "Duplicates"
FROM tbl_countries)
WHERE "Duplicates"=0;

1
select Country_id,country_title from(
   select Country_id,country_title,row_number() over (partition by country_title 
   order by Country_id  ) rn from country)a
   where rn=1;

1
在MySQL中,可以使用特殊的列函数GROUP_CONCAT
SELECT GROUP_CONCAT(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'computers' AND
    TABLE_NAME='Laptop' AND
    COLUMN_NAME NOT IN ('code')
ORDER BY ORDINAL_POSITION;

应该提到的是,MySQL中的信息模式覆盖所有数据库服务器,而不是某些特定的数据库。这就是为什么如果不同的数据库包含具有相同名称的表,则WHERE子句的搜索条件应指定模式名称:TABLE_SCHEMA='computers'
在MySQL中,可以使用CONCAT函数将字符串连接起来。我们问题的最终解决方案可以表示为MySQL语句:
SELECT CONCAT('SELECT ',
(SELECT GROUP_CONCAT(COLUMN_NAME)
 FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_SCHEMA='computers' AND
    TABLE_NAME='Laptop' AND
        COLUMN_NAME NOT IN ('code')
 ORDER BY ORDINAL_POSITION
), ' FROM Laptop');

http://www.sql-ex.ru/help/select20.php


0

在SQL中忽略重复的行。我认为这可能对你有帮助。

    SELECT res2.*
    FROM
    (SELECT res1.*,ROW_NUMBER() OVER(PARTITION BY res1.title ORDER BY res1.id)as num
     FROM 
    (select * from [dbo].[tbl_countries])as res1
    )as res2
    WHERE res2.num=1

-2

Having子句是在Oracle中查找重复条目的最简单方法,使用rowid我们可以删除重复数据。

DELETE FROM products WHERE rowid IN (
  SELECT MAX(sl) FROM (
  SELECT itemcode, (rowid) sl FROM products WHERE itemcode IN (
  SELECT itemcode FROM products GROUP BY itemcode HAVING COUNT(itemcode)>1
)) GROUP BY itemcode);

7
建议用户仅想查看数据时不要告诉他们删除数据,这是个不好的主意。 - moto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接