sql ĐẶT HÀNG BẰNG nhiều giá trị theo thứ tự cụ thể?


94

Được rồi, tôi có một bảng có khóa được lập chỉ mục và trường không được lập chỉ mục. Tôi cần tìm tất cả các bản ghi với một giá trị nhất định và trả về hàng. Tôi muốn biết liệu tôi có thể đặt hàng theo nhiều giá trị hay không.

Thí dụ:

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: muốn kết quả được sắp xếp như thế này, 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'

Vì vậy, kết quả sẽ là:

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

Cú pháp hợp lệ nhưng khi tôi thực hiện truy vấn, nó không bao giờ trả về bất kỳ kết quả nào, ngay cả khi tôi giới hạn nó ở 1 bản ghi. Có cách nào khác để làm điều này không?

Hãy coi trường x_ là kết quả kiểm tra và tôi cần xác thực tất cả các bản ghi nằm trong điều kiện. Tôi muốn sắp xếp các kết quả kiểm tra theo các giá trị không thành công, các giá trị đã vượt qua. Vì vậy, tôi có thể xác thực các giá trị không thành công trước và sau đó là các giá trị đã chuyển bằng cách sử dụng ORDER BY.

Những gì tôi không thể làm:

  • GROUP BY, vì tôi cần trả về các giá trị bản ghi cụ thể
  • WHERE x_field IN ('f', 'p', 'i', 'a'), tôi cần tất cả các giá trị vì tôi đang cố gắng sử dụng một truy vấn cho một số thử nghiệm xác thực. Và các giá trị x_field không theo thứ tự DESC / ASC

Sau khi viết câu hỏi này, tôi bắt đầu nghĩ rằng tôi cần phải suy nghĩ lại điều này, LOL!


Có thể là một công đoàn thay thế? Xây dựng các truy vấn riêng biệt theo thứ tự bạn muốn kết quả trả về, sau đó thực hiện kết hợp các truy vấn đó?
kinakuta

Câu trả lời:


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

Bạn có thể sử dụng THAM GIA TRÁI với "VALUES ('f', 1), ('p', 2), ('a', 3), ('i', 4)" và sử dụng cột thứ hai theo thứ tự của bạn -bằng biểu hiện. Postgres sẽ sử dụng Hash Join sẽ nhanh hơn nhiều so với CASE lớn nếu bạn có nhiều giá trị. Và nó dễ dàng hơn để tạo tự động.

Nếu thông tin đặt hàng này là cố định, thì nó sẽ có bảng riêng.


6
Đây là giải pháp thanh lịch nhất cho đến nay!
jnns

28

Thử:

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

Bạn đã đi đúng hướng, nhưng bằng cách chỉ đặt x_field trên giá trị F, 3 trường còn lại được coi là hằng số và không được so sánh với bất kỳ thứ gì trong tập dữ liệu.


Postgres có hỗ trợ boolean ngầm không? Nếu vậy, boolean sắp xếp như thế nào?
gbn

Tôi thích giải pháp này nhưng nó không trả lại bất cứ điều gì một lần nữa.
Phill Pafford

@gbn, Đúng và sai <đúng. Tôi đã mong đợi điều này để làm việc.
Andrew Lazarus

7
Có, nó hoạt động sự kiện ở Postgres. Lưu ý cho giải pháp này là bạn nhận được kết quả được sắp xếp theo thứ tự ngược lại. Vì vậy, bạn phải đặt các trường theo thứ tự ngược lại: ORDER BY x_field = 'A', x_field = 'I', x_field = 'P', x_field = 'F',
igo

16

Sử dụng casenút chuyển để dịch mã thành các số có thể được sắp xếp:

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

Tôi đã tìm thấy một giải pháp sạch hơn nhiều cho việc này:

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

Lưu ý: array_position cần có Postgres v9.5 trở lên.


1
Điều quan trọng cần lưu ý là array_position () chỉ khả dụng trong Postgres v9.5 trở đi, afaik.
bigsee

cảm ơn, rất thích điều này cho các phương pháp CASE. Hoạt động với số nguyên quá; array_position(ARRAY[1, 0]::integer[], x_field)
Paul Watson

7

Các CASEORDER BYgợi ý nên mọi công việc, nhưng tôi sẽ đề nghị một con ngựa của một màu sắc khác nhau. Giả sử rằng chỉ có một số lượng giá trị hợp lý x_fieldvà bạn đã biết chúng là gì, hãy tạo một kiểu liệt kê với F, P, A và I là các giá trị (cộng với bất kỳ giá trị nào khác có thể áp dụng). Các Enums sẽ sắp xếp theo thứ tự được ngụ ý bởi CREATEcâu lệnh của chúng . Ngoài ra, bạn có thể sử dụng các tên có giá trị ít ỏi — ứng dụng thực của bạn có thể có và bạn vừa che chúng để bảo mật — mà không lãng phí dung lượng, vì chỉ vị trí thứ tự được lưu trữ.


1

Bạn có thể sắp xếp theo một cột đã chọn hoặc các biểu thức khác.

Dưới đây là một ví dụ, cách sắp xếp theo kết quả của một câu lệnh viết hoa:

  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

Kết quả sẽ là một Danh sách bắt đầu bằng các hàng "IsGen = 0", tiếp theo là các hàng "IsGen = 1" và tất cả các hàng khác là cuối.

Bạn có thể thêm nhiều tham số đặt hàng hơn vào cuối:

  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

Mặc dù đoạn mã này có thể giải quyết vấn đề, nhưng nó không giải thích tại sao hoặc cách nó trả lời câu hỏi. Vui lòng bao gồm phần giải thích cho mã của bạn , vì điều đó thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Samuel Philipp

0

Đối với những người mới sử dụng ORDER BY với CASE, điều này có thể hữu ích

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

-2

bạn có thể sử dụng vị trí (văn bản trong văn bản) để sắp xếp trình tự

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.