![](/img/trans.png)
[英]MySQL select all, having one column DISTINCT whilst also returning other corresponding columns
[英]MySQL select one column DISTINCT, with corresponding other columns
ID FirstName LastName
1 John Doe
2 Bugs Bunny
3 John Johnson
我想從FirstName
列中選擇DISTINCT
結果,但我需要相應的ID
和LastName
。
結果集只需要顯示一個John
,但ID
為 1, LastName
為 Doe。
試試這個查詢
SELECT ID, FirstName, LastName FROM table GROUP BY(FirstName)
為了避免在不使用聚合函數的情況下使用GROUP BY
時出現潛在的意外結果,正如在接受的答案中所使用的那樣,因為當不使用聚合函數[原文如此]和ONLY_FULL_GROUP_BY
問題時,MySQL 可以自由檢索正在分組的數據集中的任何值。 請考慮使用排除連接。
假設 firstname 和 lastname 被唯一索引(明確) , GROUP BY
的替代方法是使用LEFT JOIN
進行排序以過濾結果集,也稱為排除 JOIN。
升序(AZ)
從 AZ 檢索按姓氏排序的不同名字
詢問
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 |
降序(ZA)
從 ZA 檢索按姓氏排序的不同名字
詢問
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 進行過濾。
表名數據
(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()
條件。
升序(AZ)
詢問
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 |
降序(ZA)
詢問
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 |
編輯
我使用有序子查詢的原始答案是在MySQL 5.7.5之前編寫的,由於ONLY_FULL_GROUP_BY
的更改,它不再適用。 請改用上述示例之一。
同樣重要的是要注意; 當ONLY_FULL_GROUP_BY
被禁用時(MySQL 5.7.5 之前的原始行為) ,在沒有聚合函數的情況下使用GROUP BY
可能會產生意想不到的結果,因為 MySQL 可以自由選擇正在分組的數據集中的任何值[sic] 。
這意味着可以檢索與檢索到的firstname
行無關的ID
或lastname
值。
警告
當與ORDER BY
使用時,MySQL GROUP BY
可能不會產生預期的結果
確保預期結果的最佳實現方法是使用有序子查詢過濾結果集范圍。
表名數據
(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,LastName
From TABLE_NAME
GROUP BY FirstName
HAVING COUNT(*) >=1
怎么樣
`SELECT
my_distinct_column,
max(col1),
max(col2),
max(col3)
...
FROM
my_table
GROUP BY
my_distinct_column`
SELECT firstName, ID, LastName from tableName GROUP BY firstName
正如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
子句中的列(本例中為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 會忽略每個名稱組內地址值的不確定性並接受查詢。 如果您根本不關心為每個組選擇非聚合列的哪個值,這可能很有用。
ANY_VALUE()
不是聚合函數,與SUM()
或COUNT()
等函數不同。 它只是起到抑制非確定性測試的作用。
不確定你是否可以用 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
否則,您可能必須使用臨時表。
請記住,在使用 group by 和 order by 時,MySQL 是唯一允許在 group by 和/或 order by 中使用不屬於 select 語句的列的數據庫。
例如:從表 group by column2 order by column3 中選擇 column1
這不會在 Postgres、Oracle、MSSQL 等其他數據庫中運行。您必須在這些數據庫中執行以下操作
從表 group by column2 order by column3 中選擇 column1, column2, column3
只是一些信息,以防您將當前代碼遷移到另一個數據庫或開始在另一個數據庫中工作並嘗試重用代碼。
您可以使用 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
SELECT DISTINCT(firstName), ID, LastName from tableName GROUP BY firstName
將是最好的選擇 IMO
SELECT DISTINCT (column1), column2
FROM table1
GROUP BY column1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.