【问题标题】:How can I select only one row for each ID in MySQL?如何在 MySQL 中为每个 ID 只选择一行?
【发布时间】:2009-06-23 18:53:28
【问题描述】:

我有一个 MySQL 表,其中包含许多具有重复 ID 的条目(出于各种原因) 所以你可能有类似的东西

ID TIME DATA
1  xx   xx
2  xx   xx
3  xx   xx
1  xx   xx
3  xx   xx

我可以通过 PHP 运行什么查询来仅选择每个 ID 一次? 所以我希望我的结果集看起来像

ID TIME DATA
1  xx   xx
2  xx   xx
3  xx   xx

【问题讨论】:

  • 结果中的 TIME 和 DATA 是什么?具有特定 id 的第一条记录的值(那么问题是为什么)?或者某些聚合函数(Count()、Sum() 甚至 Group_Concat())的结果?或者……什么?
  • DISTINCT 不能解决您的问题。

标签: php sql mysql


【解决方案1】:

@karim79 和@Matthew Jones 给出的建议DISTINCT(ID) 可以解决此问题,这是对 DISTINCT 在 SQL 中的工作方式的常见误解。它没有帮助,因为DISTINCT 总是 适用于整行,而不是单个列。括号是不相关的,因为它们在查询 SELECT (1)SELECT 1 中。

@T Pops 给出的答案在这种情况下实际上很有帮助,因为 MySQL 以非标准方式处理 GROUP BY。请参阅我对“Selecting a Column not in GROUP BY”的回答以获得解释。

另一种解决方案是创造性地使用LEFT OUTER JOIN 来查询每个ID 的第一行。例如,假设TIME 列对于给定的ID 是唯一的,您可以执行以下操作:

SELECT t1.*
FROM MyTable t1 LEFT OUTER JOIN MyTable t2
  ON (t1.ID = t2.ID AND t1.TIME > t2.TIME)
WHERE t2.ID IS NULL;

如果t1 指向组中最早的行,则 t2 中不可能有更早日期的匹配行。因此,LEFT OUTER JOIN 将找不到匹配项,并将t2.* 保留为 NULL。

【讨论】:

  • 很好的解释。我会在大约八小时后回来投票给你;-)
  • @Sinan:这是评论说 JOIN 会表现不佳吗?您应该尝试使用 EXPLAIN 来查看这样的查询的优化计划。然后将其与 GROUP BY 或 DISTINCT 查询的计划进行比较,后者通常必须使用临时表。
  • @Bill 我今天的选票用完了,所以我无法支持你的答案。重要的是要指出 DISTINCT 在这里不是一个合适的“解决方案”。您的其余解释非常清楚。我的回答没有讽刺意味,只是真的很遗憾我当时不能投票给你。
  • 谢谢!大声笑——我以为你在刻薄,好像你预计查询需要八小时才能完成,而你在投票之前一直在等待。 :-)
  • 这个问题不值得+1,直到这个答案是官方解决方案。
【解决方案2】:

看看 SELECT DISTINCT

【讨论】:

  • 你们太棒了! DISTINCT 完美运行。 Group By 也很好,但我认为在这种情况下我需要区分。感谢所有回复的人!
  • 嘿,我很想看看解决这个问题的实际 DISTINCT 查询!:)
  • @Rudebuyrock ... 加入不同的 id 会不会更好?
  • Aaah 所以你只是在寻找 id,而不是其他列。这解释了它:)
  • 但是他的问题的结果中仍然有 TIME 和 DATA 列。
【解决方案3】:

听起来您正在寻找GROUP BY

您可以使用类似以下的查询:

SELECT id, time, data GROUP BY ID

您肯定需要进行一些调整才能使该查询与您拥有的结构一起使用,但这是基本思想。

Tizag 对在 MySQL 和 PHP 中使用 GROUP BY 有很好的参考。

【讨论】:

  • +1 这实际上可以在 MySQL 中工作,因为 MySQL 以非标准方式处理 GROUP BY。
  • 真的可以保证返回时间+同一行的数据吗?
  • 不,它不保证从哪一行获取值。在实践中,它从首先物理存储的行中获取它们。如果这是 OP 想要的,那么他可以使用它(假设 MySQL 在未来版本中不会改变行为)。
  • 但是一旦它选择了一行,它会从该行中取出所有列吗?第 1 行和第 4 行的数据不需要时间吗?
【解决方案4】:

SQL 查询看起来像这样:

SELECT DISTINCT (ID), TIME, DATA FROM TableName

【讨论】:

  • 这将选择两个记录 (1,'2009-05-16','x'),(1,'2009-04-11','y') 因为它们在 TIME 和数据。
  • 我知道我忘记了什么。谢谢!
  • 这就是我不在 MySQL 中编程的原因;它太宽容了。哦,好吧。
  • @Matthew Jones:这与 MySQL 无关。 DISTINCT 在标准 SQL 中的工作方式与在 MySQL 或任何其他品牌的数据库中的工作方式相同。 DISTINCT 总是 适用于整行,而不是单列,即使您使用括号。
【解决方案5】:

向表中添加一个真正的主键,可能称为 RealId。

那么你可以:

select *
from YourTable
where realid in (
    select min(realid)
    from YourTable
    group by id
)

每个 id 会给你一行。

【讨论】:

    【解决方案6】:
    SELECT * FROM MyTable GROUP BY ID ORDER BY ID ASC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多