SQL / mysql-distinct / UNIQUE를 선택하지만 모든 열을 반환합니까?


373
SELECT DISTINCT field1, field2, field3, ......   FROM table

다음 SQL 문을 달성하려고하지만 모든 열을 반환하기를 원합니까? 다음과 같은 것 :

SELECT DISTINCT field1, * from table

12
SELECT DISTINCT * FROM table당신을 위해 작동하지 않습니다?
ypercubeᵀᴹ

19
테이블에 PK가 있으면 모든 행은 distinct정의에 따라야합니다 . 그냥 선택하려고 DISTINCT field1하지만 어떻게 든 다른 모든 열을 반환 하려는 경우 특정 field1값에 대해 둘 이상의 값을 가진 열에 대해 어떻게됩니까? GROUP BY예를 들어 다른 열에서 일종의 집계 를 사용해야 합니다.
마틴 스미스

1
다른 행뿐만 아니라 반복되는 행을 원하면 고유 한 키워드를 제거하십시오.
Hyperboreus

2
결과가 어떻게 보일지에 대한 예를 들어 주시겠습니까? 지금까지 원하는 쿼리를 이해할 수 없습니다.
재귀

3
다음은 비슷한 질문에 대한 답변입니다. 먼저 ID가있는 고유 한 열을 얻은 다음 원래 테이블과 조인해야합니다. 하나의 열에서 DISTINCT를 선택하고 다른 여러 열을 반환
yadavr

답변:


407

다음을 기준으로 그룹을 찾고 있습니다.

select *
from table
group by field1

때로는 명확한 성명서로 작성할 수 있습니다.

select distinct on field1 *
from table

그러나 대부분의 플랫폼에서는 다른 열의 동작이 지정되어 있지 않으므로 위의 어느 것도 작동하지 않습니다. (첫 번째는 MySQL에서 사용하는 것입니다.)

별개의 필드를 가져와 매번 단일 임의의 행을 고를 수 있습니다.

일부 플랫폼 (예 : PostgreSQL, Oracle, T-SQL)에서는 창 기능을 사용하여 직접 수행 할 수 있습니다.

select *
from (
   select *,
          row_number() over (partition by field1 order by field2) as row_number
   from table
   ) as rows
where row_number = 1

다른 사람 (MySQL, SQLite)에서는 전체 테이블을 자체적으로 결합시킬 수있는 하위 쿼리를 작성해야 하므로 ( 예제 ) 권장하지 않습니다.


10
쿼리가 나를 구문 분석하지 않고 오류가 발생 The ranking function "row_number" must have an ORDER BY clause합니다. field1로 분할 한 후 order by 절을 추가해야합니다. 올바른 질문은 다음과 같습니다 select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
Ankur-m

1
감사! 저도 같은 문제에이고 해결책은이었다 GROUP BY
호아킨 Iurchuk

2
또한 Oracle (Oracle SQL Developer)에서는을 지정할 수 없습니다 select *, row_number() over (partition by field1 order by field2) as row_number from table. 선택 쿼리에서 테이블 이름 / 별칭을 명시 적으로 사용해야합니다select **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
meta4

1
@jarlh : 오늘은 ... 알다시피,이 대답은 거의 7 세이며, 내가 활동했을 때 다시 회상 할 수있는 한 그 시점이 아닙니다. 필요하다고 생각되면 답변에 태그를 다시 지정하거나 편집 할 수 있습니다.
Denis de Bernardy

2
select distinct on (field1) * from table; PostgreSQL을 또한 작동
Chilianu 보그

61

귀하의 질문의 표현에서, 당신은 주어진 필드와 같은 각 행의 다른 모든 열 값이 나열된 동일한 값에 대해 다른 값을 선택하고 싶다는 것을 이해합니다. 대부분의 DBMS는이를 허용하지 DISTINCT않으며GROUP BY 결과가 결정되지 않기 때문에 .

이것을 다음과 같이 생각하십시오 : 당신 field1이 두 번 이상 발생하면, 어떤 값 field2이 나열 될 것 입니까 ( field1두 행에서 동일한 값을 가지지 만 두 행에서 두 개의 다른 값을 가지면 field2).

그러나 집계 함수 (표시하려는 모든 필드에 대해 명시 적으로)를 사용하는 GROUP BY대신 다음을 대신 사용할 수 있습니다 DISTINCT.

SELECT field1, MAX(field2), COUNT(field3), SUM(field4), .... FROM table GROUP BY field1

4
이 솔루션의 +1 우리가 할 수 있도록 SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1하고, FIELD2는, 3, 4 ,,, 그들이 문자 필드가 될 수 정수 (또는 다른 자리) 할 필요가 없습니다 아니라
줄기

부울 열에 갇힐 때까지 잘 작동했습니다. MIN (동적) 열 값이 true 인 경우에도 false로 수정됩니다. 6 분 전에 부울 – signonsridhar를 처리하는 데 사용할 수있는 다른 집계 함수. 합계 (동적)를 1로 거짓을 변경
signonsridhar

1
큰 제안, 내가 더 보편적이라고 생각하는 내 솔루션으로 이끌었습니다.
개렛 심슨

@signonsridhar는 부울을 int로 캐스팅하고 합계를 사용합니다. 예sum(cast(COL as int)) > 0
Drew

26

문제를 올바르게 이해했다면 방금 한 것과 비슷합니다. DISTINCT의 유용성을 모든 데이터에 적용하지 않고 지정된 필드로 제한 할 수 있기를 원합니다.

집계 함수없이 GROUP BY를 사용하는 경우 GROUP BY 필드는 DISTINCT 파일입니다.

당신이 쿼리를하는 경우 :

SELECT * from table GROUP BY field1;

field1의 단일 인스턴스를 기반으로 모든 결과를 표시합니다.

예를 들어 이름, 주소 및 도시가있는 테이블이있는 경우입니다. 한 사람이 여러 주소를 기록했지만 그 사람을 위해 하나의 주소 만 원하면 다음과 같이 쿼리 할 수 ​​있습니다.

SELECT * FROM persons GROUP BY name;

결과적으로 해당 이름의 한 인스턴스 만 주소와 함께 표시되고 다른 인스턴스는 결과 테이블에서 생략됩니다. 주의 : 제출 한 파일에 firstName, lastName과 같은 원자 값이 있으면 둘 다 그룹화 할 수 있습니다.

SELECT * FROM persons GROUP BY lastName, firstName;

두 사람이 같은 성을 가지고 있고 lastName으로 만 그룹화하면 그 사람 중 하나가 결과에서 생략됩니다. 이러한 사항을 고려해야합니다. 도움이 되었기를 바랍니다.


단지 MYSQL에 대한 - 허용 대답에 언급 한 바와 같이, SQL의 대부분의 화신을 위해 일 것이다
개렛 심슨에게

15
SELECT  c2.field1 ,
        field2
FROM    (SELECT DISTINCT
                field1
         FROM   dbo.TABLE AS C
        ) AS c1
        JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1

C alias그것없이 작동 할 수있는 이유는 무엇 입니까? 라인에서FROM dbo.TABLE AS C
Talha

2
RedGate SQLPrompt를 사용했기 때문이라고 생각합니다. 내가 구성한 방식에 따라 불필요한 경우에도 항상 별칭을 추가합니다. "만약의 경우"
Stormy

이것은 나에게 유망한 것처럼 보였지만 여전히 구별되는 field1이 아닌 모든 행을 다시 가져 왔습니다. :(
Michael Fever

13

정말 좋은 질문입니다. 나는 이미 유용한 답변을 읽었지만 더 정확한 설명을 추가 할 수 있습니다.

추가 정보를 쿼리하지 않는 한 GROUP BY 문으로 쿼리 결과 수를 줄이는 것은 쉽습니다. 다음 테이블 'locations'가 있다고 가정 해 봅시다.

--country-- --city--
 France      Lyon
 Poland      Krakow
 France      Paris
 France      Marseille
 Italy       Milano

이제 쿼리

SELECT country FROM locations
GROUP BY country

결과 :

--country--
 France
 Poland
 Italy

그러나 다음 쿼리

SELECT country, city FROM locations
GROUP BY country

"프랑스"의 오른쪽에있는 필드에서 읽고 싶은 프랑스 도시 "리옹", "파리"또는 "마르세유"중 어느 것을 컴퓨터가 어떻게 알 수 있기 때문에 MS SQL에서 오류가 발생합니까?

두 번째 쿼리를 수정하려면이 정보를 추가해야합니다. 이를 수행하는 한 가지 방법은 MAX () 또는 MIN () 함수를 사용하여 모든 후보 중에서 가장 큰 값 또는 가장 작은 값을 선택하는 것입니다. MAX () 및 MIN ()은 숫자 값에만 적용 할 수있을뿐 아니라 알파벳 순서의 문자열 값을 비교합니다.

SELECT country, MAX(city) FROM locations
GROUP BY country

결과 :

--country-- --city--
 France      Paris
 Poland      Krakow
 Italy       Milano

또는:

SELECT country, MIN(city) FROM locations
GROUP BY country

결과 :

--country-- --city--
 France      Lyon
 Poland      Krakow
 Italy       Milano

알파벳 (또는 숫자) 순서의 양쪽 끝에서 값을 선택하는 것이 좋으면 이러한 기능은 좋은 솔루션입니다. 그러나 이것이 사실이 아닌 경우 어떻게해야합니까? 예를 들어 문자 'M'으로 시작하는 특정 특성의 값이 필요하다고 가정합니다. 이제 상황이 복잡해집니다.

지금까지 내가 찾은 유일한 해결책은 전체 쿼리를 하위 쿼리에 넣고 외부에서 추가 열을 직접 작성하는 것입니다.

SELECT
     countrylist.*,
     (SELECT TOP 1 city
     FROM locations
     WHERE
          country = countrylist.country
          AND city like 'M%'
     )
FROM
(SELECT country FROM locations
GROUP BY country) countrylist

결과 :

--country-- --city--
 France      Marseille
 Poland      NULL
 Italy       Milano

5

@aryaxt의 훌륭한 질문-5 년 전에 요청했기 때문에 큰 질문이라고 말할 수 있으며 오늘 답변을 찾으려고 노력했습니다.

나는 이것을 포함하기 위해 허용 된 답변을 편집하려고 시도했지만 내 편집으로 그것을 만들지 않는 경우 :

테이블이 크지 않고 기본 키가 자동 증가 정수라고 가정하면 다음과 같이 할 수 있습니다.

SELECT 
  table.*
FROM table
--be able to take out dupes later
LEFT JOIN (
  SELECT field, MAX(id) as id
  FROM table
  GROUP BY field
) as noDupes on noDupes.id = table.id
WHERE
  //this will result in only the last instance being seen
  noDupes.id is not NULL

5

시험

SELECT table.* FROM table 
WHERE otherField = 'otherValue'
GROUP BY table.fieldWantedToBeDistinct
limit x

3

당신은 WITH절로 할 수 있습니다 .

예를 들면 다음과 같습니다.

WITH c AS (SELECT DISTINCT a, b, c FROM tableName)
SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c

또한 WITH절 쿼리 에서 선택한 행만 선택할 수 있습니다.


2

SQL Server의 경우 dense_rank 및 추가 윈도우 기능을 사용하여 지정된 열에서 값이 중복 된 모든 행과 열을 가져올 수 있습니다. 여기 예가 있습니다 ...

with t as (
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all
    select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6'
), tdr as (
    select 
        *, 
        total_dr_rows = count(*) over(partition by dr)
    from (
        select 
            *, 
            dr = dense_rank() over(order by col1, col2, col3),
            dr_rn = row_number() over(partition by col1, col2, col3 order by other)
        from 
            t
    ) x
)

select * from tdr where total_dr_rows > 1

이것은 col1, col2 및 col3의 각 고유 조합에 대해 행 수를 취합니다.


너무 복잡하고 SQL의 특정 하나의 구현
개렛 심슨

1
select min(table.id), table.column1
from table 
group by table.column1

이것은 나를 위해 일했다!! fetch_array ()를 사용하는 경우 암시 적으로 행 이름을 호출하는 대신 인덱스 레이블을 통해 각 행을 호출해야합니다. 내가 가지고있는 예를 쓸 수있는 문자가 충분하지 않습니다 : X sorry !!
Brandon Printiss

0
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30

ORDER BY난 그냥 여기 예를 넣어 가지고, 당신은 또한이에 ID 필드를 추가 할 수 있습니다


단지 MYSQL에 대한 - 허용 대답에 언급 한 바와 같이, SQL의 대부분의 화신을 위해 일 것이다
개렛 심슨에게

0

다른 곳에서 이것을 찾았지만 이것은 작동하는 간단한 솔루션입니다.

 WITH cte AS /* Declaring a new table named 'cte' to be a clone of your table */
 (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY val1 DESC) AS rn
 FROM MyTable /* Selecting only unique values based on the "id" field */
 )
 SELECT * /* Here you can specify several columns to retrieve */
 FROM cte
 WHERE rn = 1

MSSQL에서 작동
Michael Fever

-1

검색어와 같은 중복 항목을 확인하려는 필드에 GROUP BY를 추가하십시오.

SELECT field1, field2, field3, ......   FROM table GROUP BY field1

중복 레코드를 제외하도록 field1을 검사합니다.

또는 당신은 같은 쿼리를 할 수 있습니다

SELECT *  FROM table GROUP BY field1

field1의 중복 레코드가 SELECT에서 제외됨


1
GROUP BY 절은 선택된 필드와 일치해야합니다. 그렇지 않으면 다음과 같은 오류가 발생합니다.filed2 must appear in the GROUP BY clause or be used in an aggregate function
Viuu -a

-2

GROUP BY 절에 모든 필드를 포함하십시오.


3
이것이 좋은 대답이 되려면 의미에 대해 좀 더 자세히 설명해야합니다.
Robbert

-2

내부 쿼리로 수행 할 수 있습니다

$query = "SELECT * 
            FROM (SELECT field
                FROM table
                ORDER BY id DESC) as rows               
            GROUP BY field";

2
이것은 질문에 대한 답변이 아닙니다. OP는 테이블의 모든 데이터를 가져
Garrett Simpson

-3
SELECT * from table where field in (SELECT distinct field from table)

7
그것은 일을하지 않습니다. 하위 쿼리에서 고유 한 열을 선택했지만 where 절은 해당 값을 가진 모든 열을 가져옵니다. 따라서 'field'열이 고유 한 열이 아닌 경우 'select * from table'을 작성하는 것만 큼 쿼리가 좋습니다.이 경우 해당 열의 고유 항목이 전혀 필요하지 않습니다.
Ankur-m

-3

SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1은 세 열의 값이 모두 테이블에서 고유 한 경우 작동합니다.

예를 들어 이름에 대해 동일한 값이 여러 개 있지만 선택한 열의 성 및 기타 정보가 다른 경우 레코드가 결과 집합에 포함됩니다.


2
이는 영업 이익은 테이블의 모든 데이터를 얻으려고 노력했다 질문에 대답하지만, 하나의 필드의 중복 포함하는 행을 제거하지 않습니다
개렛 심슨

-3

나는 사용하는 것이 좋습니다

SELECT  * from table where field1 in 
(
  select distinct field1 from table
)

이렇게하면 여러 행에 걸쳐 field1에 동일한 값이 있으면 모든 레코드가 반환됩니다.


1
와 다르지 않습니다 SELECT * FROM table;. 훨씬 더 느립니다.
신 김

먼저 답변을 시도하십시오.
셰리프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.