Tại sao NULL được sắp xếp trước?


20

Tại sao khi chúng ta có một giá trị NULL trong một cột và chúng ta sắp xếp theo giá trị tăng dần, các NULL được sắp xếp trước?

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

kết quả trong

NULL
1
2
3
4

Tôi cứ nghĩ rằng NULL có nghĩa là "Không xác định" hoặc có thể là "Không biết". Nếu đó là sự thật, họ sẽ không sắp xếp cuối cùng, vì giá trị có thể lớn hơn tất cả các giá trị khác? (Hay đây là một tùy chọn sắp xếp ở đâu đó?)

Tôi đang dùng SQL Server 2008R2, nhưng tôi nghi ngờ điều này đúng trên tất cả các Máy chủ SQL và có lẽ trên tất cả các RDBMS.


1
Oracle liệt kê nó cuối cùng. Điều đó làm tôi khó chịu một lần, tin rằng nó sẽ hoạt động như SQL Server.
Andrei Rînea

2
"Nếu đó là sự thật, họ sẽ không sắp xếp cuối cùng, vì giá trị có thể lớn hơn tất cả các giá trị khác". Giá trị có thể nhỏ hơn tất cả các giá trị khác. Đối với tôi, thật trực quan khi một giá trị chim ưng như null nên ở cấp thấp hơn. Và thực tế, vì trong thực tế, bạn thường muốn sử dụng descđặt hàng để hiển thị những thứ lớn nhất hoặc gần đây nhất, trong trường hợp đó tôi rất vui vì những thứ vô giá trị là cuối cùng.
mahemoff

Cơ sở dữ liệu làm những gì bạn bảo nó làm. Nếu bạn biết rằng dữ liệu của bạn chứa null và bạn có một số lý do kinh doanh để sắp xếp dữ liệu theo một cách nhất định, thì bạn cần chỉ định rằng trong truy vấn hoặc mã / chế độ xem xử lý / hiển thị dữ liệu. Không bao giờ để sắp xếp theo hành vi cơ sở dữ liệu mặc định.
gì cần thiết

Câu trả lời:


19

BOL : Giá trị của NULL chỉ ra rằng giá trị này là không xác định. Giá trị của NULL khác với giá trị trống hoặc bằng không. Không có hai giá trị null bằng nhau. So sánh giữa hai giá trị null hoặc giữa NULL và bất kỳ giá trị nào khác, trả về không xác định vì giá trị của mỗi NULL không xác định.

NULL có nghĩa là không biết. Không có giải thích khác là hợp lệ.

Nếu đó là sự thật, họ sẽ không sắp xếp cuối cùng, vì giá trị có thể lớn hơn tất cả các giá trị khác?

Không thể có được . Không có giá trị tiềm năng . Không biết là không biết là không biết.

Về lý do tại sao nó xuất hiện đầu tiên, thay vì cuối cùng, điều này không được phục vụ cho các tiêu chuẩn SQL được công bố và không may để lại theo quyết định của nhà cung cấp RDBMS:

Wikipedia : Tiêu chuẩn SQL không xác định rõ ràng thứ tự sắp xếp mặc định cho Nulls. Thay vào đó, trên các hệ thống tuân thủ, Nulls có thể được sắp xếp trước hoặc sau tất cả các giá trị dữ liệu bằng cách sử dụng các mệnh đề NULLS FIRST hoặc NULLS LAST của danh sách ORDER BY, tương ứng. Tuy nhiên, không phải tất cả các nhà cung cấp DBMS đều thực hiện chức năng này. Các nhà cung cấp không thực hiện chức năng này có thể chỉ định các phương pháp điều trị khác nhau để sắp xếp Null trong DBMS.


Vì vậy, đó là một cuộc gọi phán xét. Điều đó làm cho rất nhiều ý nghĩa. Cảm ơn!
Richard

6

Bạn đúng NULLcó nghĩa là 'Không xác định' hoặc 'Uknownn' hoặc 'Chưa biết' hoặc 'Không áp dụng'. Nhưng không có lý do để đặt Nulls đầu tiên hoặc cuối cùng. Nếu chúng ta không biết các giá trị thực tế, thì tehy có thể nhỏ hoặc lớn.

Tôi nghĩ tiêu chuẩn để xác định hành vi mong muốn của Nulls trong quá trình sắp xếp là:

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

Thật không may, SQL-Server chưa áp dụng cú pháp này. Nếu tôi không sai PostgreSQL và Oracle có nó.

Một cách giải quyết:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

Một giải pháp khác cần điều chỉnh tùy thuộc vào kiểu dữ liệu - nhưng sẽ không tốt, vì nó không thể sử dụng một chỉ mục trên (test):

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer

Theo cách này, ĐẶT HÀNG B CONG COALESCE (thử nghiệm, 2147483647) Máy chủ SQL không thể sử dụng Index.
Ardalan Shahgholi

3

Tôi không biết tại sao nó lại được thực hiện theo cách đó, nhưng theo định nghĩa, NULLS không thể được so sánh với không phải NULLS, vì vậy họ phải đi vào lúc bắt đầu hoặc kết thúc (câu trả lời của Mark bao gồm nhiều chi tiết hơn).

Để có được hành vi bạn muốn - Theo như tôi biết, không có tùy chọn sắp xếp nào để đặt null cuối cùng, vì vậy bạn phải đánh bại nó bằng cách sử dụng một cột được tính toán để buộc chúng kéo dài. Tuy nhiên, trong SQL Server, bạn không thể đặt hàng theo cột được tính ( CASE WHEN ...) khi dữ liệu của bạn chứa toán tử đã đặt ( UNION ALL). Vì thế:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

Sẽ làm việc để sắp xếp null cuối cùng. Nếu bạn phải sử dụng UNION(hoặc EXCEPThay INTERSECTS) để tạo bộ dữ liệu của bạn, sau đó đổ dữ liệu của bạn vào một bảng tạm thời như trên.


... hoặc sử dụng đầu ra UNIONed làm bảng dẫn xuất.
Andriy M

0

Nếu bạn đang xử lý số, bạn cũng có thể sử dụng

ORDER BY -test DESC

NULLlà các giá trị thấp nhất có thể, do đó DESCđặt chúng ở cuối. Trong khi đó, các giá trị không null có dấu đảo ngược nên DESCthực sự là một ASCgiá trị thực. Điều này sẽ nhanh hơn CASEvà tôi cho rằng trình tối ưu hóa truy vấn cũng có thể sử dụng các chỉ mục trên testcột.


3
Không, nó sẽ không thể sử dụng một chỉ mục cho loại. Trừ khi bạn có một chỉ mục trên biểu thức tính toán (- test).
ypercubeᵀᴹ

1
Thông minh, mặc dù chỉ giới hạn ở dữ liệu số (dù sao cũng phù hợp với ví dụ của OP). Tôi không chắc liệu điều này có thực sự nhanh hơn việc sử dụng CASE hay không nhưng tôi chắc chắn rằng nó sẽ không sử dụng một chỉ mục (trừ khi đó là những gì @ ypercubeᵀᴹ nói - nhưng sau đó một biểu thức CASE có thể được lập chỉ mục theo cùng một cách chính xác).
Andriy M
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.