MySQL은 다른 열과 함께 하나의 열 DISTINCT를 선택합니다.


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

내가 선택하려는 DISTINCT로부터 결과 FirstName열을,하지만 난 상응하는 필요 IDLastName.

결과 집합 은 1 개만 표시하고 1 개와 Doe John는 표시해야합니다 .IDLastName


1
별명이 다른 가장 낮은 ID에 속하는 성을 원하십니까?
토마스 랭 스턴

3
최고의 것을 선택해야하는 논리는 무엇입니까? John Doe와 John Johnson이 서로 다른 두 John이기 때문에 표시되기를 원한다고 생각합니다.
judda

4
DISTINCT기능이 아닙니다. 모든 답변 DISTINCT()이 잘못되었습니다. 다음에 오류를 표시하지 않으면 오류가 표시됩니다 SELECT.
질문 오버플로

1
ALL distinct라는 단어 다음에 괄호를 사용한 은 실제로 틀립니다. 구별은 함수가 아니므로 매개 변수를 승인 할 수 없습니다. 구별되는 괄호는 단순히 무시됩니다. 괄호가 "복잡한 데이터 유형"을 형성하는 PostgreSQL을 사용하지 않는 한
Used_By_Already

답변:


192

이 쿼리를 사용해보십시오

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

16
어떤 행이 반환되는지 어떻게 알 수 있습니까?
윌리엄 Entriken

27
@Full MySQL 문서 에 따르면 : "서버는 각 그룹에서 값을 자유롭게 선택할 수 있으므로 동일하지 않으면 선택한 값이 결정되지 않습니다." 실제로 ORDER BY 절과 함께 이러한 종류의 쿼리를 성공적으로 사용했습니다. 예를 들어 ORDER BY id ASC / DESC를 추가하면 쿼리를 실행할 때마다 MySQL이 일관된 결과를 반환합니다. 그러나 누군가 프로덕션 환경에서 문서화되지 않은 기능을 사용해야하는지 확신 할 수 있습니다.
Arunas Junevicius

2
OP에는 mysql 버전이 언급되어 있지 않습니다.
diEcho

2
@sinaza 5.7.5+는 변경된 GROUP BY핸들링에
fyrye

3
ID 나 성이 모두 집계되거나 그룹화 기능의 일부가 아니기 때문에 only_full_group_by 모드에서는 작동하지 않습니다. 도움!
ihodonald

63

DISTINCT키워드는 정말 당신이 그것을 기대하고있는 방식으로 작동하지 않습니다. 사용 SELECT DISTINCT col1, col2, col3하면 실제로 모든 고유 {col1, col2, col3} 튜플을 선택하는 것입니다.


14
이것을 Brian에게 지적 해 주셔서 감사합니다. GROUP BY를 사용하여 동일한 결과를 얻는 방법에 대한 예를 제공 할 수 있습니까?
mr

59

사용하는 경우 잠재적으로 예기치 않은 결과를 방지하려면 GROUP BY집계 함수 않고, 허용 대답에 사용되는 MySQL을 검색 할 무료이기 때문에, 모든 집계 함수 사용하지 않을 경우 그룹화 된 데이터 세트 내에서 값을 [원문] 와 문제 ONLY_FULL_GROUP_BY. 제외 조인 사용을 고려하십시오.

제외 조인-명확한 엔터티

firstName을 가정하고 LASTNAME 고유 색인 (모호)를 , 대안 것은 GROUP BY하여 정렬을 사용하는 것 LEFT 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로도 필터링 할 수 있습니다.

데모보기

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 |

정렬 된 하위 쿼리

편집하다

정렬 된 하위 쿼리를 사용하는 원래의 답변 은 MySQL 5.7.5 이전에 작성되었으며로 변경 되었으므로 더 이상 적용 할 수 없습니다 ONLY_FULL_GROUP_BY. 위의 제외 조인 예제를 대신 사용하십시오.

참고하는 것도 중요합니다. 때 ONLY_FULL_GROUP_BY비활성화 (5.7.5 MySQL의 이전 동작이 일본어) 의 사용 GROUP BYMySQL이 자유롭게 선택할 수 있기 때문에 집합 기능이없는 예기치 않은 결과를 산출 할 수 ANY 그룹화되는 데이터 세트 내의 값 [SIC] .

검색된 행 과 연관되지 않은ID 또는 lastname값을 검색 할 수 있음을 의미합니다 .firstname


경고

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

결과

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

비교

GROUP BY와 함께 사용할 때 예기치 않은 결과를 보여주기 위해ORDER BY

질문

SELECT * FROM table_name GROUP BY FirstName ORDER BY ID DESC

결과

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

3
가장 완벽한 답변. 첫 번째 쿼리에서 'ID desc'를 'ID asc'로 변경하면 'John Doe'또는 'John Johnson'을 검색 할 수 있습니다. 두 번째 쿼리에서 'ID desc'를 변경해도이 효과가 없습니다.
carla

postgres에서는 mysql을 모르므로 그룹의 ID가 필요합니다.
Sachin Prasad

하나의 SELECT 문에있는 GROUP BY 열 A ORDER BY 열 B가 항상 최신 버전의 MyriaDB에서 올바르게 작동합니까?
닐 데이비스

@NealDavis MariaDB 매뉴얼에 따라이 유스 Ordering is done after grouping.케이스에는 해당되지 않으며, 추가로 MariaDB는 서브 쿼리 에서 SQL없이 ORDER BY를 무시 합니다 LIMIT. 당신은을 사용할 것이다 Window Function당신은 당신의 질문을해야 더 명확한 설명을 위해 DBA의 stackexchange 이 MySQL의에 관한 질문이기 때문에,
fyrye

1
@NateS 아니요, GROUP BY특정 값을 강제하기 위해 해당 열에서 집계 함수를 사용하지 않으면 그룹화 된 데이터 세트 내에서 값을 선택할 수 있습니다. 그래서 lastname또는 id정렬 된 행의에서 올 수 있습니다. 원래 하위 쿼리 예제는 기본적으로 허용 MySQL <= 5.7.4되었지만 기술적으로 여전히 문제가 있습니다. 이 방법은 ORDER BY무작위 선택을 방지하는 데 도움이되지만 이론적으로는 가능하지만 ORDER BY하위 쿼리 를 사용하지 않는 것보다 확률이 훨씬 낮습니다 .
fyrye

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

2
추가하면 HAVING검색어가 50 % 느려집니다.
Butkus

HAVING COUNT (*)> = 1이 거짓 인 경우가 있습니까?
Angelos Makrygiorgos


3

어때요?

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

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

그렇지 않으면 임시 테이블을 사용해야 할 수도 있습니다.


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 절에 없으며 GROUP BY 절의 열에 기능적으로 의존하지 않는 집계되지 않은 열 'mydatabase.table_name.id'를 포함합니다. 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(). 비결정론에 대한 테스트를 억제하는 역할을합니다.


명확하게하기 위해, 나는 구체적 ANY_VALUE()으로 내 대답 으로 사용할 것을 제안하지 않았 으며 의견은 모호하고 예측할 수없는 결과 집합을 방지하는 데 중점을 둡니다. 함수 이름에서 알 수 있듯이 선택한 행의 값이 검색 될 수 있습니다. 내가 사용하는 것이 좋습니다 것 MAX또는 MIN그 대신.
fyrye

0

MySQL을 기준으로 그룹 별 및 순서를 사용하는 경우 select 문에 포함되지 않은 그룹 별 및 / 또는 순서별로 열을 사용할 수있는 유일한 데이터베이스입니다.

따라서 예를 들면 다음과 같습니다. 테이블 그룹에서 column1을 column2별로, column3을 순서대로 선택하십시오.

Postgres, Oracle, MSSQL 등과 같은 다른 데이터베이스에서는 비행하지 않습니다. 해당 데이터베이스에서 다음을 수행해야합니다.

테이블 그룹에서 column2별로 column1, column2, column3을 선택하십시오.

현재 코드를 다른 데이터베이스로 마이그레이션하거나 다른 데이터베이스에서 작업을 시작하고 코드 재사용을 시도하는 경우를 대비 한 정보입니다.


-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

2
에 의해 주문을 그룹화 할 때이 항상 결과를 예상 얻을 수 없습니다
fyrye

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

최고의 내기 IMO가 될 것입니다


32
이것은 작동하지 않으며 ID와 성도 별개의 평가에 사용합니다.
Ludo-기록 종료

2
이것은 DISTINCT (firstName, ID, LastName)와 동일합니다
Tom Taylor

-4
SELECT DISTINCT (column1), column2
FROM table1
GROUP BY column1

1
DISTINCT()기능이 아닙니다. 또한 DISTINCT와 GROUP BY는 동일한 작업을 수행하므로 아무런 이유가 없습니다.
Marki555

이것은 효율적인 설명이 아니므로 DISTINCT 또는 Group By를 모두 사용하지 않아야합니다.
heshanlk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.