ID FirstName LastName
1 John Doe
2 Bugs Bunny
3 John Johnson
我想从FirstName列中选择DISTINCT结果,但我需要相应的ID和LastName。
结果集只需要显示一个John,但是ID为1,LastName为Doe。
ID FirstName LastName
1 John Doe
2 Bugs Bunny
3 John Johnson
我想从FirstName列中选择DISTINCT结果,但我需要相应的ID和LastName。
结果集只需要显示一个John,但是ID为1,LastName为Doe。
当前回答
为了避免在不使用聚合函数的情况下使用GROUP BY时可能出现的意想不到的结果,就像在接受的答案中使用的那样,因为MySQL在不使用聚合函数并且只有_full_group_by时可以自由地检索被分组的数据集中的任何值。请考虑使用排除连接。
排除连接-明确的实体
假设姓和名是唯一索引(无歧义),GROUP BY的另一种替代方法是使用LEFT JOIN筛选结果集,也称为排除JOIN。
看到演示
升序(A-Z)
从A-Z中检索按姓排序的不同的姓
查询
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND t1.lastname > t2.lastname
WHERE t2.id IS NULL;
结果
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |
降序(Z-A)
从Z-A中检索按姓排序的不同的姓
查询
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND t1.lastname < t2.lastname
WHERE t2.id IS NULL;
结果
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
然后可以根据需要对结果数据进行排序。
排除连接-模糊实体
如果姓和名的组合不是唯一的(不明确),并且有多个相同值的行,则可以通过在JOIN条件上包含OR条件来过滤结果集,也可以通过id进行过滤。
看到演示
table_name数据
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson'),
(4, 'John', 'Doe'),
(5, 'John', 'Johnson')
查询
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND (t1.lastname > t2.lastname
OR (t1.firstname = t1.firstname AND t1.lastname = t2.lastname AND t1.id > t2.id))
WHERE t2.id IS NULL;
结果
| id | firstname | lastname |
|----|-----------|----------|
| 1 | John | Doe |
| 2 | Bugs | Bunny |
复合IN()子查询-明确的实体
对于较大的数据集,使用排除连接可能非常慢。 如果有明确的条目,另一种方法是对MIN/MAX聚合子查询使用Composite IN()标准。
示范
升序(A-Z)
查询
SELECT t1.*
FROM table_name AS t1
WHERE (t1.firstname, t1.lastname) IN(
SELECT firstname, MIN(lastname)
FROM table_name
GROUP BY firstname
)
结果
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |
降序(Z-A)
查询
SELECT t1.*
FROM table_name AS t1
WHERE (t1.firstname, t1.lastname) IN(
SELECT firstname, MAX(lastname)
FROM table_name
GROUP BY firstname
)
结果
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
复合IN()依赖子查询-不明确的实体
通过在id列上添加带有MIN/MAX的依赖子查询,可以将相同的理论从Ambiguous Exclusion连接应用到复合IN()子查询方法。
示范
查询
SELECT t1.*
FROM table_name AS t1
WHERE t1.id IN(
SELECT MIN(id)
FROM table_name
WHERE (t1.firstname, t1.lastname) IN(
SELECT firstname, MIN(lastname)
FROM table_name
GROUP BY firstname
)
GROUP BY firstname, lastname
);
结果
| id | firstname | lastname |
|----|-----------|----------|
| 1 | John | Doe |
| 2 | Bugs | Bunny |
命令子查询
EDIT
我最初使用有序子查询的答案是在MySQL 5.7.5之前编写的,由于ONLY_FULL_GROUP_BY的变化,它不再适用。请用上面的例子代替。
同样重要的是要注意;当ONLY_FULL_GROUP_BY被禁用时(MySQL 5.7.5之前的原始行为),使用GROUP BY而不使用聚合函数可能会产生意想不到的结果,因为MySQL可以在被分组的数据集中自由选择任何值[原文]。
这意味着可以检索与所检索的姓名行不关联的ID或姓值。
警告
在MySQL中,GROUP BY在使用ORDER BY时可能不会产生预期的结果
参见测试用例示例
确保预期结果的最佳实现方法是使用有序子查询筛选结果集范围。
table_name数据
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson')
查询
SELECT * FROM (
SELECT * FROM table_name ORDER BY ID DESC
) AS t1
GROUP BY FirstName
结果(MySQL 5.6)
| ID | first | last |
|----|-------|---------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
比较
演示GROUP BY与ORDER BY结合使用时的意外结果
查询
SELECT * FROM table_name GROUP BY FirstName ORDER BY ID DESC
结果(MySQL 5.6)
| ID | first | last |
|----|-------|-------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |
其他回答
DISTINCT关键字并没有按照您期望的方式工作。当你使用SELECT DISTINCT col1, col2, col3时,你实际上选择了所有唯一的{col1, col2, col3}元组。
试试这个查询
SELECT ID, FirstName, LastName FROM table GROUP BY(FirstName)
您可以使用组by来显示不同的值和相应的字段。
select * from tabel_name group by FirstName
现在你得到了这样的输出:
ID FirstName LastName
2 Bugs Bunny
1 John Doe
如果你想回答的话
ID FirstName LastName
1 John Doe
2 Bugs Bunny
然后使用这个查询,
select * from table_name group by FirstName order by ID
正如fyrye所指出的,被接受的答案与MySQL的旧版本有关,其中只有_full_group_by还没有被引入。使用MySQL 8.0.17(在本例中使用),除非禁用ONLY_FULL_GROUP_BY,否则将得到以下错误消息:
mysql> SELECT id, firstName, lastName FROM table_name GROUP BY firstName;
错误1055 (42000):SELECT列表中的表达式#1不在GROUP BY子句中,并且包含未聚合的列mydatabase.table_name。id',它不依赖于GROUP BY子句中的列;这与sql_mode=only_full_group_by不兼容
fyrye没有提到,但在https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html中描述的一种方法是将ANY_VALUE()函数应用到不在GROUP by子句中的列(本例中的id和lastName):
mysql> SELECT ANY_VALUE(id) as id, firstName, ANY_VALUE(lastName) as lastName FROM table_name GROUP BY firstName;
+----+-----------+----------+
| id | firstName | lastName |
+----+-----------+----------+
| 1 | John | Doe |
| 2 | Bugs | Bunny |
+----+-----------+----------+
2 rows in set (0.01 sec)
如上所述,
在这种情况下,MySQL忽略每个名称组中地址值的不确定性并接受查询。如果您不关心为每个组选择非聚合列的哪个值,那么这可能很有用。与SUM()或COUNT()等函数不同,ANY_VALUE()不是一个聚合函数。它只是抑制了不确定性的测试。
SELECT DISTINCT (column1), column2
FROM table1
GROUP BY column1