MySQL选择一列DISTINCT,以及相应的其他列

时间:2011-05-11 15:53:16

标签: mysql

ID   FirstName   LastName
1      John        Doe
2      Bugs        Bunny
3      John        Johnson

我想从DISTINCT列中选择FirstName个结果,但我需要相应的IDLastName

结果集只需显示一个John,但ID为1,而LastName为Doe。

12 个答案:

答案 0 :(得分:165)

尝试此查询

 SELECT ID, FirstName, LastName FROM table GROUP BY(FirstName)

答案 1 :(得分:54)

DISTINCT关键字并不像您期望的那样真正起作用。当您使用SELECT DISTINCT col1, col2, col3时,您实际上正在选择所有唯一的{col1,col2,col3}元组。

答案 2 :(得分:49)

修改

原始答案是在 MySQL 5.7.5 之前编写的,由于ONLY_FULL_GROUP_BY的默认更改,该答案不再适用。同样重要的是要注意,当禁用ONLY_FULL_GROUP_BY时,使用没有聚合函数的GROUP BY会产生意外结果,因为MySQL可以自由选择 ANY 值数据集被分组[sic]

假设firstname和lastname是唯一索引的,GROUP BY的替代方法是使用LEFT JOIN进行排序以过滤结果集。 See Demonstration

按降序检索按姓氏排序的不同名字(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;

#Results
| id | firstname | lastname |
|----|-----------|----------|
|  2 |      Bugs |    Bunny |
|  3 |      John |  Johnson |

按升序检索由姓氏排序的不同名字(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;

#Results
| id | firstname | lastname |
|----|-----------|----------|
|  2 |      Bugs |    Bunny |
|  1 |      John |      Doe |

然后,您可以根据需要订购结果数据。

如果名字和姓氏组合不是唯一的并且您有多行具有相同值,则可以通过在联接上包含OR条件来筛选结果集以选择特定ID。 See the demonstration

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;

#Results
| id | firstname | lastname |
|----|-----------|----------|
|  1 |      John |      Doe |
|  2 |      Bugs |    Bunny |

警告

使用MySQL GROUP BYORDER BY一起使用时,并不会始终产生预期结果。请参阅:Test Case Example

确保预期结果的最佳实现方法是使用像这样的子查询过滤结果集范围。

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

#Results
| ID | first |    last |
|----|-------|---------|
|  2 |  Bugs |   Bunny |
|  3 |  John | Johnson |

对战

SELECT * FROM table_name GROUP BY FirstName ORDER BY ID DESC

#Results
| ID | first |  last |
|----|-------|-------|
|  2 |  Bugs | Bunny |
|  1 |  John |   Doe |

答案 3 :(得分:21)

SELECT ID,LastName 
From TABLE_NAME 
GROUP BY FirstName 
HAVING COUNT(*) >=1

答案 4 :(得分:3)

怎么样

`SELECT 
    my_distinct_column,
    max(col1),
    max(col2),
    max(col3)
    ...
 FROM
    my_table 
 GROUP BY 
    my_distinct_column`

答案 5 :(得分:2)

不确定您是否可以使用MySQL执行此操作,但可以在T-SQL中使用CTE

; WITH tmpPeople AS (
 SELECT 
   DISTINCT(FirstName),
   MIN(Id)      
 FROM People
)
SELECT
 tP.Id,
 tP.FirstName,
 P.LastName
FROM tmpPeople tP
JOIN People P ON tP.Id = P.Id

否则您可能必须使用临时表。

答案 6 :(得分:2)

SELECT firstName, ID, LastName from tableName GROUP BY firstName

答案 7 :(得分:1)

正如fyrye所指出的那样,可接受的答案与尚未引入ONLY_FULL_GROUP_BY的MySQL的旧版本有关。使用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中的列子句(在此示例中为idlastName

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会忽略每个名称组中地址值的不确定性,并接受查询。如果您根本不在乎为每个组选择未聚合列的哪个值,这可能会很有用。与ANY_VALUE()SUM()之类的函数不同,COUNT()不是聚合函数。它只是起到抑制不确定性测试的作用。

答案 8 :(得分:0)

请记住,当使用group by并按顺序排列时,MySQL是唯一的数据库,它允许在组中使用和/或逐个使用不属于select语句的列。

所以例如: 选择column1 从表 按列2分组 按列3排序

这不会在Postgres,Oracle,MSSQL等其他数据库中出现。您必须在这些数据库中执行以下操作

选择column1,column2,column3 从表 按列2分组 按列3排序

只是一些信息,以防您将当前代码迁移到另一个数据库或开始在另一个数据库中工作并尝试重用代码。

答案 9 :(得分:-2)

您可以使用group 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

答案 10 :(得分:-3)

SELECT DISTINCT(firstName), ID, LastName from tableName GROUP BY firstName

将是IMO最好的选择

答案 11 :(得分:-4)

add_filter( 'bbp_get_topic_post_count', 'bbp_get_topic_post_count', 10, 2 );