【问题标题】:Remove duplicates in Select query based on one column根据一列删除选择查询中的重复项
【发布时间】:2019-08-19 18:27:41
【问题描述】:

我想选择不重复的ids 并在选择语句中保留行'5d' 而不是'5e'

表格

id | name
1  | a
2  | b
3  | c
5  | d
5  | e

我试过了:

SELECT id, name 
FROM table t
INNER JOIN (SELECT DISTINCT id FROM table) t2 ON t.id = t2.id

【问题讨论】:

  • 确保始终指定要应用的规则。 “并保留第 5d 行而不是 5e”仅告诉我们 'd' 胜过 'e' 而我们不知道为什么。如果不是“d”和“e”而是“a”和“z”或其他任何名称怎么办? 'd' 比'e' 好,因为它在字母表中出现在'e' 之前?还是因为它不是元音?那么,如果出现重复:如何决定要保留的值?
  • 我要保留最早的插入,删除最新的
  • 定义“最早”?根据定义,表是无序集。这意味着您必须为数据提供订单。

标签: sql sql-server tsql


【解决方案1】:

你也可以使用ROW_NUMBER():

SELECT id, name
FROM (
    SELECT id, name, ROW_NUMBER() OVER(PARTITION BY id ORDER BY name) rn 
    FROM mytable
) x
WHERE rn = 1

这将保留具有最小name 的记录(因此'5d' 将位于'5e' 之前)。使用此技术,您还可以在存在重复项的另一列上使用排序条件(使用 MIN() 的聚合查询无法做到这一点)。此外,使用窗口函数的查询通常比等效的聚合查询执行得更好。

【讨论】:

    【解决方案2】:

    如果您想保留名称最小的行,则可以使用not exists

    select t.* from tablename t
    where not exists (
      select 1 from tablename
      where id = t.id and name < t.name
    )
    

    【讨论】:

    • 我对这个 sn-p 有点困惑,你能解释一下它是如何工作的吗?
    • @bentz123 此查询仅选择表中没有其他行具有相同id 但较少name 的行(按字母顺序)。所以它返回不同的 id,每个 id 中 name 最少。
    【解决方案3】:

    对于给定的示例,使用 min() 的聚合将起作用。

    SELECT id,
           min(name) name
           FROM table
           GROUP BY id;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-04
      • 2017-07-11
      • 2017-09-16
      • 1970-01-01
      • 2018-12-01
      • 2014-09-23
      • 2022-12-22
      • 1970-01-01
      相关资源
      最近更新 更多