如何在 MySQL 中为每个 ID 只选择一行?
Posted
技术标签:
【中文标题】如何在 MySQL 中为每个 ID 只选择一行?【英文标题】:How can I select only one row for each ID in MySQL? 【发布时间】: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 不能解决您的问题。 【参考方案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 在未来版本中不会改变行为)。 见***.com/questions/1023347/… 但是一旦它选择了一行,它会从该行中取出所有列吗?第 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
【讨论】:
以上是关于如何在 MySQL 中为每个 ID 只选择一行?的主要内容,如果未能解决你的问题,请参考以下文章