동일한 SELECT 문에서 DISTINCT 및 ORDER BY를 사용하는 방법은 무엇입니까?


117

다음 문을 실행 한 후 :

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC

데이터베이스에서 다음 값을 얻습니다.

test3
test3
bildung
test4
test3
test2
test1

하지만 다음과 같이 중복을 제거하고 싶습니다.

bildung
test4
test3
test2
test1

DISTINCT를 사용하려고했지만 하나의 문에서 ORDER BY와 함께 작동하지 않습니다. 도와주세요.

중대한:

  1. 나는 그것을 시도했다 :

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC

    작동하지 않습니다.

  2. CreationDate에 의한 주문은 매우 중요합니다.


1
어떻게 작동하지 않습니까? 잘못된 출력?
Fedearne 2011 년

답변:


195

문제는에서 사용 된 열 ORDER BYDISTINCT. 이렇게하려면 집계 함수 를 사용하여 정렬하고 a GROUP BY를 사용하여 DISTINCT작업을 수행해야합니다.

다음과 같이 시도하십시오.

SELECT DISTINCT Category, MAX(CreationDate) 
FROM MonitoringJob 
GROUP BY Category 
ORDER BY MAX(CreationDate) DESC, Category

99
범주별로 그룹화하는 경우에는 DISTINCT 키워드도 필요하지 않습니다.
MatBailie 2011 년

18

확장 된 정렬 키 열

원하는 작업이 작동하지 않는 이유는 첫 번째 쿼리의 경우 다음 과 같은 SQL논리적 작업 순서 때문입니다 .

  • FROM MonitoringJob
  • SELECT Category, CreationDate즉, 소위 확장 정렬 키 열 추가
  • ORDER BY CreationDate DESC
  • SELECT Category즉 , 결과에서 확장 된 정렬 키 열을 다시 제거합니다 .

따라서 SQL 표준 확장 정렬 키 열 기능 덕분에 SELECT절에 일시적으로 추가되므로 절에 없는 항목으로 정렬 하는 것이 완전히 가능 합니다.

그렇다면 왜 이것이 작동하지 DISTINCT않습니까?

DISTINCT연산 을 추가하면 SELECT과 사이에 추가됩니다 ORDER BY.

  • FROM MonitoringJob
  • SELECT Category, CreationDate
  • DISTINCT
  • ORDER BY CreationDate DESC
  • SELECT Category

하지만 지금은 확장 된 정렬 키 열 CreationDate 을 사용하여 DISTINCT작업 의 의미 가 변경되었으므로 결과가 더 이상 동일하지 않습니다. 이것은 우리가 원하는 것이 아니므로 SQL 표준과 모든 합리적인 데이터베이스 모두 이러한 사용을 금지합니다.

해결 방법

다음과 같은 표준 구문으로 에뮬레이션 할 수 있습니다.

SELECT Category
FROM (
  SELECT Category, MAX(CreationDate) AS CreationDate
  FROM MonitoringJob
  GROUP BY Category
) t
ORDER BY CreationDate DESC

또는 Prutswonder에 의해 표시된 것처럼 간단히 (이 경우)

SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
ORDER BY CreationDate DESC

여기에서 SQL DISTINCT 및 ORDER BY에 대해 자세히 블로그에 올렸습니다 .


1
나는 당신이 어떻게 DISTINCT ON작동 하는지 착각하고 여기에서 도움이되지 않는다고 생각합니다 . 괄호 안의 표현은 구별 성 (그룹화 조건)을 결정하는 데 사용됩니다. 동일한 범주가 다른 경우 그 CreationDate중 하나만 결과에 나타납니다! 내가 어떻게 든 틀렸는 지 궁금했기 때문에 블로그 게시물에 예제 데이터베이스를로드하여 다시 확인했습니다. DISTINCT ON거기에 제공 한 쿼리는 총 1000 개의 결과 (많은 중복 포함 length)를 생성했지만 아래 쿼리는 140 (고유) 값만.
Inkling

@Inkling : 시간 내 주셔서 감사합니다. OP는 명시 적으로 "중복"제거를 원합니다. OP의 문구를 참조하십시오. "하지만 이와 같이 중복을 제거하고 싶습니다" . 내 블로그 게시물에서 쿼리를 복사 할 때 실수를했을 것입니다. DISTINCT(no ON) 를 사용하는 쿼리 와 DISTINCT ON. 후자는 중복 된 길이를 명시 적으로 제거하지 않고 중복 된 제목을 제거합니다. 여기 내 대답이 완전히 옳다고 생각합니다.
Lukas Eder

1
내 요점은 귀하의 DISTINCT ON조건이 잘못된 조건을 사용하여 중복을 제거 한다는 것 입니다. 블로그 게시물에서 DISTINCT ON쿼리는 실제로 중복 된 제목을 제거 하지만 그 DISTINCT위 의 쿼리와 그 아래의 쿼리 ( "구문 설탕"이라고 주장하는) 모두 중복 길이를 제거 합니다. 이는 아마도 전체 목표 일 것입니다. 여기에도 동일한 사항이 적용됩니다. OP는 중복 카테고리를 원합니다. 쿼리 처럼 CreationDates 를 복제하지 않고 중복 제거DISTINCT ON . 여전히 나를 믿지 않는다면 스스로 시험해보십시오.
Inkling

6

MAX (CreationDate)의 출력이 원하지 않는 경우-원래 질문의 예에서와 같이-유일한 대답은 Prashant Gupta의 대답에 대한 두 번째 진술입니다.

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

설명 : 인라인 함수에서 ORDER BY 절을 사용할 수 없으므로이 경우 Prutswonder의 답변에있는 문을 사용할 수 없습니다.이 경우 외부 선택을 넣을 수없고 MAX (CreationDate) 부분을 버릴 수 없습니다.


2

[Category] 및 [CreationDate] 열의 값을 원하는 경우이 코드를 사용하십시오.

SELECT [Category], MAX([CreationDate]) FROM [MonitoringJob] 
             GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

또는 [Category] 열의 값만 원하는 경우이 코드를 사용합니다.

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

원하는대로 모든 고유 한 레코드를 갖게됩니다.


그 중괄호 []는 완전히 혼란 스럽습니다 ...이 유효한 SQL 구문입니까?
m13r 2014-08-27

1
대괄호는 Order, event 등과 같은 키워드를 이스케이프하기위한 것이므로 (예를 들어) 테이블에라는 열이있는 경우 구문 분석 오류를 발생시키는 SQL을 중지하는 대신 Event쓸 수 있습니다 . [Event]Event
Ben Maxfield 2016-10-24

1

2) CreationDate의 순서는 매우 중요합니다.

원래 결과는 "test3"에 여러 결과가 있음을 나타냅니다.

항상 MAX를 사용하여 Group By의 중복 항목을 제거하고 근본적인 질문이 무엇인지 잊어 버리거나 무시하는 것은 매우 쉽습니다.

OP는 아마도 MAX를 사용하는 것이 그에게 마지막 "생성"을 제공하고 MIN을 사용하면 첫 번째 "생성"을 제공한다는 것을 깨달았을 것입니다.


3
이것은 실제로 질문에 대한 대답이 아닌 것 같습니다. 질문에 MAX대한 대답으로 독립된 것보다는 다른 응답자가 사용하는에 대한 의견 인 것 같습니다 .
DaveyDaveDave

0
if object_id ('tempdb..#tempreport') is not null
begin  
drop table #tempreport
end 
create table #tempreport (
Category  nvarchar(510),
CreationDate smallint )
insert into #tempreport 
select distinct Category from MonitoringJob (nolock) 
select * from #tempreport  ORDER BY CreationDate DESC

0

하위 쿼리로 작동합니다.

    SELECT distinct(Category) from MonitoringJob  where Category in(select Category from MonitoringJob order by CreationDate desc);

음 ... 그럴 것 같지 않아요. 외부 선택은 정렬되지 않습니다.
Hossam El-Deen

작동하지 않습니다. 이것이 작동하지 않기 때문에 여기에 있습니다
Amirreza

-1

Distinct는 레코드를 오름차순으로 정렬합니다. 설명 순서로 정렬하려면 다음을 사용하십시오.

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

CreationDate 필드를 기준으로 레코드를 정렬하려면이 필드가 select 문에 있어야합니다.

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC

12
이것은 실행되지만 OP에 필요한 것을 제공하지 않습니다. OP는 Category와 CreateDate의 고유 한 조합이 아닌 고유 한 카테고리를 원합니다. 이 코드는 각각 다른 CreationDate 값을 가진 동일한 Category의 여러 인스턴스를 생성 할 수 있습니다.
MatBailie 2011 년

-1

CTE를 사용할 수 있습니다.

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC

-3

다음으로 시도하지만 대용량 데이터에는 유용하지 않습니다.

SELECT DISTINCT Cat FROM (
  SELECT Category as Cat FROM MonitoringJob ORDER BY CreationDate DESC
);

4
"TOP 또는 FOR XML도 지정하지 않는 한 ORDER BY 절은 뷰, 인라인 함수, 파생 테이블, 하위 쿼리 및 공통 테이블 식에서 유효하지 않습니다."
TechplexEngineer

주문 기준에 CreationDate 열을 지정하지 않았기 때문에 작동하지 않습니다.
Mauro Bilotti

1
@TechplexEngineer 귀하의 의견이 올바르지 않습니다. ORDER BY하위 쿼리에서 사용 하는 것은 절대적으로 유효합니다. 그리고 누군가가 당신의 잘못된 댓글에 찬성 투표를했습니다.
Racil Hilan 2014 년

나는 이것을 시도하고 @TechplexEngineer와 동일한 오류가 있습니다. 케이스와 함께 맞춤 주문을 사용하고 있습니다.
Ege Bayrak

-4

내부 쿼리를 사용하여 수행 할 수 있습니다.

$query = "SELECT * 
            FROM (SELECT Category  
                FROM currency_rates                 
                ORDER BY id DESC) as rows               
            GROUP BY currency";

-5
SELECT DISTINCT Category FROM MonitoringJob ORDER BY Category ASC

2
만든 날짜별로 정렬해야합니다 !! 그것은 매우 중요합니다
RR

주문하고 싶은 칼럼을 직접 추가하는 것은 불가능합니까? 귀하의 예는 알파벳 순서로 항목을 표시했습니다. 만든 날짜로 주문해야하는 경우 추가하기 만하면됩니다. 그렇게 어렵지 않습니다.
Furicane 2011 년

8
-1 : OP가 시도했지만 작동하지 않았습니다. 불가능하고 OP를 후원 할 때 분명히 그 사실을 무시했기 때문입니다. 요점은 DISTINCT 연산자가 각각 잠재적으로 다른 생성 날짜를 가진 동일한 Category 값을 가진 여러 레코드를 대조한다는 것입니다. 따라서 DISTINCT를 사용할 때 논리적으로 불가능합니다. 이렇게하면 필요한 논리가 DISTINCT 대신 GROUP BY에 푸시되어 생성 날짜에 집계 (MAX)가 허용됩니다.
MatBailie 2011 년

실제로 OP가 한 일을 자세히 살펴보면 절대적으로 잘못된 SQL입니다. 저는 단 한 번의 실수도하지 않았으며 주어진 결과는 그가 요청한 것과 일치합니다. 나는 -1에 신경 쓰지 않고 다음 번에 사람을 수정하기 전에 읽으십시오. 감사합니다.
Furicane 2011 년

8
"정말 어렵지 않습니다"라고 말하면서 CreationDate 필드를 직접 추가 할 것을 제안합니다. 그렇게하면 잘못된 SQL이 생성됩니다. OP를 후원하고 OP를 원래 게시 한 진술로 되 돌리는 조언을 제공하고 DISTINCT와 DISTINCT에없는 필드의 주문 사이의 경합을 알아 차리지 못한 것에 대해 -1을 받았습니다. 또한 'b'는 't'앞에오고 '1'은 '4'앞에옵니다. 따라서 OP가 제공하는 결과는 알파벳 순서가 아닙니다. 다음 번에 (더 자세히) 읽어보십시오.
MatBailie 2011 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.