SQL ORDER BY 여러 값을 특정 순서로?


94

좋아, 색인이 생성 된 키와 색인이 생성되지 않은 필드가있는 테이블이 있습니다. 특정 값을 가진 모든 레코드를 찾고 행을 반환해야합니다. 여러 값으로 주문할 수 있는지 알고 싶습니다.

예:

id     x_field
--     -----
123    a
124    a
125    a
126    b
127    f
128    b
129    a
130    x
131    x
132    b
133    p
134    p
135    i

pseudo : 결과가 다음과 같이 정렬되기를 원합니다. where ORDER BY x_field = 'f', 'p', 'i', 'a'

SELECT *
FROM table
WHERE id NOT IN (126)
ORDER BY x_field 'f', 'p', 'i', 'a'

따라서 결과는 다음과 같습니다.

id     x_field
--     -----
127    f
133    p
134    p
135    i
123    a
124    a
125    a
129    a

구문은 유효하지만 쿼리를 실행하면 레코드를 1 개로 제한하더라도 결과가 반환되지 않습니다. 이것에 대해 다른 방법이 있습니까?

x_field를 테스트 결과로 생각하고 조건에 해당하는 모든 레코드의 유효성을 검사해야합니다. 실패한 값, 통과 한 값으로 테스트 결과를 정렬하고 싶었습니다. 따라서 실패한 값을 먼저 확인한 다음 ORDER BY를 사용하여 전달 된 값을 확인할 수 있습니다.

내가 할 수없는 것 :

  • 특정 레코드 값을 반환해야하므로 GROUP BY
  • WHERE x_field IN ( 'f', 'p', 'i', 'a'), 여러 유효성 검사 테스트에 하나의 쿼리를 사용하려고하므로 모든 값이 필요합니다. x_field 값은 DESC / ASC 순서가 아닙니다.

이 질문을 쓴 후 나는 이것을 다시 생각할 필요가 있다고 생각하기 시작했습니다, LOL!


대신 노조일까요? 결과를 반환 할 순서대로 별도의 쿼리를 구성한 다음 해당 쿼리를 통합 하시겠습니까?
kinakuta 2011-06-13

답변:


181
...
WHERE
   x_field IN ('f', 'p', 'i', 'a') ...
ORDER BY
   CASE x_field
      WHEN 'f' THEN 1
      WHEN 'p' THEN 2
      WHEN 'i' THEN 3
      WHEN 'a' THEN 4
      ELSE 5 --needed only is no IN clause above. eg when = 'b'
   END, id

29

"VALUES ( 'f', 1), ( 'p', 2), ( 'a', 3), ( 'i', 4)"와 함께 LEFT JOIN을 사용하고 주문에서 두 번째 열을 사용할 수 있습니다. -표현으로. Postgres는 값이 많은 경우 거대한 CASE보다 훨씬 빠른 해시 조인을 사용합니다. 그리고 자동 생성이 더 쉽습니다.

이 주문 정보가 고정 된 경우 자체 테이블이 있어야합니다.


6
이것은 가장 우아한 솔루션입니다!
jnns

28

시험:

ORDER BY x_field='F', x_field='P', x_field='A', x_field='I'

올바른 길을 가고 있었지만 x_field를 F 값에만두면 나머지 3 개는 상수로 처리되고 데이터 세트의 어떤 것과도 비교되지 않았습니다.


Postgres는 암시 적 부울을 지원합니까? 그렇다면 부울은 어떻게 정렬됩니까?
gbn 2011-06-13

이 솔루션이 마음에 들었지만 다시는 아무것도 반환하지 않았습니다.
Phill Pafford 2011 년

@gbn, 예 및 false <true. 나는 이것이 효과가있을 것이라고 기대했을 것이다.
Andrew Lazarus

7
예, Postgres에서 이벤트를 작동합니다. 이 솔루션에 대한 참고 사항은 결과가 역순으로 정렬된다는 것입니다. 따라서 필드를 역순으로 입력해야합니다. ORDER BY x_field = 'A', x_field = 'I', x_field = 'P', x_field = 'F',
igo

16

case스위치를 사용 하여 코드를 정렬 할 수있는 숫자로 변환합니다.

ORDER BY
  case x_field
  when 'f' then 1
  when 'p' then 2
  when 'i' then 3
  when 'a' then 4
  else 5
  end

10

나는 이것에 대한 훨씬 더 깨끗한 해결책을 찾았습니다.

ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)

참고 : array_position에는 Postgres v9.5 이상이 필요합니다.


1
array_position ()은 Postgres v9.5 이상인 afaik에서만 사용할 수 있습니다.
bigsee

감사합니다. CASE 방법보다 이것을 선호했습니다. 정수에서도 작동합니다. array_position(ARRAY[1, 0]::integer[], x_field)
Paul Watson

7

CASEORDER BY제안은 모든 일을해야한다,하지만 난 다른 색의 말을 제안하겠습니다. 적절한 수의 값만 x_field있고 이미 그 값을 알고 있다고 가정하고 F, P, A 및 I를 값으로 사용하여 열거 형 을 만듭니다 (다른 가능한 값이 적용됨). 열거 형은 CREATE문에 암시 된 순서대로 정렬됩니다 . 또한 서수 위치 만 저장되므로 공간을 낭비하지 않고 의미있는 값 이름을 사용할 수 있습니다. 실제 응용 프로그램에서 사용할 수 있으며 기밀을 위해 마스크를 마스킹했습니다.


1

선택한 열 또는 다른 표현식을 기준으로 정렬 할 수 있습니다.

다음은 case-statement의 결과를 기준으로 주문하는 방법의 예입니다.

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END

결과는 "IsGen = 0"행으로 시작하여 "IsGen = 1"행과 끝이 다른 모든 행으로 시작하는 목록이됩니다.

끝에 주문 매개 변수를 더 추가 할 수 있습니다.

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END,
         col1,
         col2

이 코드 스 니펫은 문제를 해결할 수 있지만 질문에 대한 이유 또는 답을 설명하지 않습니다. 게시물의 품질을 향상시키는 데 도움이되는 코드에 대한 설명을 포함 해주세요 . 미래에 독자를 위해 질문에 답하고 있으며 해당 사용자는 코드 제안 이유를 모를 수 있습니다.
Samuel Philipp

0

CASEORDER BY 를 처음 사용하는 사람에게는 유용 할 수 있습니다.

ORDER BY 
    CASE WHEN GRADE = 'A' THEN 0
         WHEN GRADE = 'B' THEN 1
         ELSE 2 END

-2

순서를 정렬하기 위해 위치 (텍스트의 텍스트)를 사용할 수 있습니다.

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