Kiểm tra nếu có bất kỳ cột nào là NULL


16

Tôi đang cố gắng tìm ra một truy vấn dễ dàng mà tôi có thể làm để kiểm tra xem một bảng lớn có danh sách các mục có ít nhất MỘT giá trị trống (NULL / trống) trong cột BẤT K ..

Tôi cần một cái gì đó như

SELECT * FROM table AS t WHERE ANY(t.* IS NULL)

Tôi không muốn phải làm

SELECT * FROM table AS t WHERE t.c1 = NULL OR t.c2 = NULL OR t.c3 = NULL

Đây sẽ là một truy vấn lớn.

Câu trả lời:


16

Một phần mở rộng cho câu trả lời của @ db2 với ít hơn (đọc: không) sắp xếp bằng tay:

DECLARE @tb nvarchar(512) = N'dbo.[table]';

DECLARE @sql nvarchar(max) = N'SELECT * FROM ' + @tb
    + ' WHERE 1 = 0';

SELECT @sql += N' OR ' + QUOTENAME(name) + ' IS NULL'
    FROM sys.columns 
    WHERE [object_id] = OBJECT_ID(@tb);

EXEC sys.sp_executesql @sql;

8

Bạn nên liệt kê tất cả các cột theo nhận xét của JNK.

WHERE c1 IS NULL OR c2 IS NULL OR c3 IS NULL

Một cách tiếp cận ít hiệu quả hơn mà tránh điều này là dưới đây mặc dù.

;WITH xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' AS ns) 
SELECT * 
FROM   YourTable AS T1 
WHERE (
    SELECT T1.* 
    FOR XML PATH('row'), ELEMENTS XSINIL, TYPE
  ).exist('//*/@ns:nil') = 1 

(Dựa trên câu trả lời SO này)


5

Không có cú pháp tích hợp đẹp, nhưng Management Studio có một vài tính năng tiện lợi để tạo truy vấn nhanh chóng.

Trong Object Explorer, đi sâu vào bảng bạn muốn, mở rộng nó, sau đó kéo toàn bộ thư mục "Cột" vào một trình soạn thảo truy vấn trống. Điều này sẽ thêm một danh sách các cột được phân tách bằng dấu phẩy vào truy vấn.

Tiếp theo, mở Tìm và Thay thế. Đặt "Tìm gì" thành ,và đặt "Thay thế bằng" thành IS NULL OR(với khoảng trắng ở đầu) rồi nhấn Thay thế tất cả. Bạn sẽ phải dọn sạch cái cuối cùng trong chuỗi bằng tay.

Nó vẫn xấu, nhưng nó ít tốn công sức.


4

Nhiều giải pháp cho: một số null, tất cả null, một cột và nhiều cột cộng với làm cho nó NHANH CHÓNG bằng cách sử dụng Top 1

Nếu bạn cần kiểm tra nhiều cột, bạn có thể sử dụng như sau:

Column_1 Column_2 Column_3
-------- -------- --------
1        2        NULL
1        NULL     NULL
5        6        NULL

Đầu tiên , kiểm tra NULL và đếm chúng:

select 
    sum(case when Column_1 is null then 1 else 0 end) as Column_1, 
    sum(case when Column_2 is null then 1 else 0 end) as Column_2, 
    sum(case when Column_3 is null then 1 else 0 end) as Column_3,
from TestTable 

Mang lại số lượng NULL:

Column_1  Column_2  Column_3
0         1         3

Trong đó kết quả là 0, không có NULL.

Thứ hai , hãy tính những người không phải là NULL:

select 
    sum(case when Column_1 is null then 0 else 1 end) as Column_1, 
    sum(case when Column_2 is null then 0 else 1 end) as Column_2, 
    sum(case when Column_3 is null then 0 else 1 end) as Column_3,
from TestTable

... Nhưng vì chúng tôi đang đếm những người không phải NULL ở đây, nên điều này có thể được đơn giản hóa thành:

select 
    count(Column_1) as Column_1, 
    count(Column_2) as Column_2, 
    count(Column_3) as Column_3,
from TestTable

Một trong hai sản lượng:

Column_1  Column_2  Column_3
3         2         0

Trong đó kết quả là 0, cột hoàn toàn được tạo thành từ NULL.

Cuối cùng , nếu bạn chỉ cần kiểm tra một cột cụ thể, thì TOP 1 sẽ nhanh hơn vì nó sẽ dừng ở lần truy cập đầu tiên. Sau đó, bạn có thể tùy ý sử dụng số đếm (*) để đưa ra kết quả kiểu boolean:

select top 1 'There is at least one NULL' from TestTable where Column_3 is NULL

select count(*) from (select top 1 'There is at least one NULL' AS note from TestTable where Column_3 is NULL) a

0 = Không có NULL, 1 = Có ít nhất một NULL

hoặc là

select top 1 'There is at least one non-NULL' AS note from TestTable where Column_3 is not NULL

select count(*) from (select top 1 'There is at least one non-NULL' AS note from TestTable where Column_3 is not NULL) a

0 = Chúng đều là NULL, 1 = Có ít nhất một không phải NULL

Tôi hi vọng cái này giúp được.


Mặc dù điều này có vẻ khá hữu ích, tôi cảm thấy có nghĩa vụ phải lưu ý rằng đó không phải là điều OP yêu cầu - họ muốn nội dung của mỗi hàng có giá trị NULL, không chỉ là kiểm tra xem có tồn tại không.
RDFozz

Đủ công bằng. Tôi nghĩ rằng tôi chỉ đọc nó khác nhau. Tôi đã tập trung vào phần "... kiểm tra nếu một bảng lớn có ...", vì vậy ... Boolean (trong trường hợp của tôi là Boolean-ish). Nhưng nếu, theo "danh sách các mục", ý anh là hàng, thì bạn hoàn toàn đúng.
jwolf

Chỉ cần xem lại điều này. Tôi chắc chắn đã giải thích sai câu hỏi - nên đã suy ra rằng anh ta đang tìm kiếm các hàng là kết quả. Tôi nghĩ rằng tôi cũng đã hiểu sai ý của anh ấy bởi HUGE. Ban đầu tôi nghĩ anh ta có nghĩa là đắt tiền về mặt tính toán nhưng bây giờ tôi chỉ nghĩ anh ta có nghĩa là rộng với các cột nên Arron và DB2 đã hiểu đúng, cả về cách đọc và giải pháp (tùy thuộc vào việc mệt mỏi hơn: não của bạn hoặc ngón tay của bạn)
jwolf

2

UNPIVOT dịch các cột thành hàng. Trong quá trình nó loại bỏ các giá trị NULL ( tham chiếu ).

Đưa ra đầu vào

create table #t
(
    ID  int primary key,
    c1  int null,
    c2  int null
);

insert #t(id, c1, c2)
values
    (1, 12, 13),
    (2, null, 14),
    (3, 15, null),
    (4, null, null);

truy vấn UNPIVOT

select
    ID, ColName, ColValue
from
(
    select *
    from #t
) as p
unpivot
(
    ColValue for ColName in
    (c1, c2)                  -- explicit source column names required
) as unpvt;

sẽ tạo ra đầu ra

| ID | ColName | ColValue |
|----|---------|----------|
| 1  | c1      | 12       |
| 1  | c2      | 13       |
| 2  | c2      | 14       |
| 3  | c1      | 15       |

Đáng buồn là hàng 4 đã bị loại bỏ hoàn toàn vì nó chỉ có NULL! Nó có thể được giới thiệu lại một cách thuận tiện bằng cách đưa một giá trị giả vào truy vấn nguồn:

select
    ID, ColName, ColValue
from
(
    select
        -5 as dummy,               -- injected here, -5 is arbitrary
        *
    from #t
) as p
unpivot
(
    ColValue for ColName in
    (dummy, c1, c2)                -- referenced here
) as unpvt;

Bằng cách tổng hợp các hàng trên ID, chúng ta có thể đếm các giá trị khác null. So sánh với tổng số cột trong bảng nguồn sẽ xác định các hàng có chứa một hoặc nhiều NULL.

select
    ID
from
(
    select -5 as dummy, *
    from #t
) as p
unpivot
(
    ColValue for ColName in
    (dummy, c1, c2)
) as unpvt
group by ID
having COUNT(*) <> 3;

Tôi tính 3 là
số cột trong bảng nguồn #t
+ 1 cho cột giả được chèn
- 1 cho ID, không được UNPIVOTED

Giá trị này có thể đạt được khi chạy bằng cách kiểm tra các bảng danh mục.

Các hàng ban đầu có thể được lấy bằng cách tham gia vào kết quả.

Nếu các giá trị khác ngoài NULL được điều tra, chúng có thể được bao gồm trong mệnh đề where:

...
) as unpvt
where ColValue <> ''      -- will eliminate empty strings

Thảo luận

Điều này đòi hỏi một định danh được thực hiện thông qua UNPIVOT. Một chìa khóa sẽ là tốt nhất. Nếu không tồn tại, có thể được chèn bởi hàm cửa sổ ROW_NUMBER () , mặc dù điều này có thể tốn kém để thực thi.

Tất cả các cột phải được liệt kê rõ ràng bên trong mệnh đề UNPIVOT. Chúng có thể được kéo vào bằng cách sử dụng SSMS, như @ db2 đề xuất. Nó sẽ không năng động khi định nghĩa bảng chagnes, như đề xuất của Aaron Bertrand sẽ là. Đây là trường hợp cho hầu hết tất cả SQL, tuy nhiên.

Đối với dữ liệu khá hạn chế của tôi, kế hoạch thực hiện là quét chỉ mục cụm và tổng hợp luồng. Điều này sẽ tốn bộ nhớ hơn so với việc quét thẳng bảng và nhiều mệnh đề OR.

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.