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。
当前回答
正如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 ID, FirstName, LastName FROM table GROUP BY(FirstName)
SELECT DISTINCT (column1), column2
FROM table1
GROUP BY column1
SELECT DISTINCT(firstName), ID, LastName from tableName GROUP BY firstName
在我看来这是最好的选择吗
为了避免在不使用聚合函数的情况下使用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 |
如何
`SELECT
my_distinct_column,
max(col1),
max(col2),
max(col3)
...
FROM
my_table
GROUP BY
my_distinct_column`