2011-12-21 42 views
18

Tôi đã tự hỏi về khả năng đếm các cột rỗng của hàng trong SQL, tôi có một bảng Khách hàng có giá trị nullable, đơn giản là tôi muốn một truy vấn trả về một int của số của các cột null cho hàng nhất định (một số khách hàng nhất định).Đếm các cột Null liên tiếp trong SQL

+0

Đó không phải là những gì bạn nên muốn làm trong sql – zerkms

+0

Đối với sự tò mò của riêng tôi, tại sao bạn lại muốn biết điều này? – UnhandledExcepSean

+0

RDBMS là gì? Các cột là gì? Họ có phải tất cả cùng một kiểu dữ liệu không? –

Trả lời

27

Phương pháp này chỉ định 1 hoặc 0 cho các cột rỗng và thêm tất cả chúng lại với nhau. Hy vọng rằng bạn không có quá nhiều cột nullable để thêm lên đây ...

SELECT 
    ((CASE WHEN col1 IS NULL THEN 1 ELSE 0 END) 
    + (CASE WHEN col2 IS NULL THEN 1 ELSE 0 END) 
    + (CASE WHEN col3 IS NULL THEN 1 ELSE 0 END) 
    ... 
    ... 
    + (CASE WHEN col10 IS NULL THEN 1 ELSE 0 END)) AS sum_of_nulls 
FROM table 
WHERE Customer=some_cust_id 

Lưu ý, bạn cũng có thể làm được điều này có lẽ một chút cú pháp hơn sạch với IF() nếu RDBMS của bạn hỗ trợ nó.

SELECT 
    (IF(col1 IS NULL, 1, 0) 
    + IF(col2 IS NULL, 1, 0) 
    + IF(col3 IS NULL, 1, 0) 
    ... 
    ... 
    + IF(col10 IS NULL, 1, 0)) AS sum_of_nulls 
FROM table 
WHERE Customer=some_cust_id 

Tôi đã thử nghiệm mẫu này với một bảng và nó có vẻ hoạt động bình thường.

+0

'IF()' cũng có thể trông gọn gàng hơn về mặt cú pháp, nhưng 'CASE' được hỗ trợ phổ biến hơn. Tuy nhiên, để tiếp tục dòng này, từ giải pháp phổ quát nhất đến giải pháp sạch nhất, tôi sẽ gợi ý những điều sau: 'SELECT ((col1 IS NULL) + (col2 IS NULL) + ...) AS sum_of_nulls FROM ...'. –

+0

Cách đếm? –

+1

@ImanMarashi Tôi không chắc chắn những gì bạn đang yêu cầu. Kết quả của truy vấn này là một cột số nguyên duy nhất đại diện cho số cột NULL cho mỗi hàng. –

-1

Không có cách đơn giản để làm như vậy sẽ có hàng đếm. Về cơ bản, bạn phải liệt kê tất cả các cột có thể là null trong một biểu thức.

Vì vậy, cho một bảng với các cột có thể vô a, b,c, bạn có thể làm điều này:

SELECT key_column, COALESCE(a,0) + COALESCE(b,0) + COALESCE(c,0) null_col_count 
    FROM my_table 
+0

Điều này sẽ không hoạt động. Nếu a, b, c không phải là số, nó sẽ gây ra lỗi. Nếu chúng là số, nó sẽ trả về kết quả sai. –

0

Thật không may, trong một câu lệnh SQL tiêu chuẩn mà bạn sẽ phải nhập mỗi cột bạn muốn kiểm tra, để kiểm tra tất cả các chương trình bạn có thể sử dụng T-SQL. Một lời cảnh báo mặc dù, đảm bảo bạn đang làm việc với chính hãng NULLS, bạn có thể có giá trị được lưu trữ trống mà cơ sở dữ liệu sẽ không nhận ra như là một NULL đúng (tôi biết điều này nghe có vẻ kỳ lạ).

Bạn có thể tránh điều này bằng cách bắt các giá trị trống và NULLS trong một tuyên bố như thế này:

CASE WHEN col1 & '' = '' THEN 1 ELSE 0 END 

Hoặc trong một số cơ sở dữ liệu như Oracle (không chắc chắn nếu có bất kỳ những người khác), bạn sẽ sử dụng:

CASE WHEN col1 || '' = '' THEN 1 ELSE 0 END 
0

Bạn không nêu RDBMS. Đối với SQL Server 2008 ...

SELECT CustomerId, 
     (SELECT COUNT(*) - COUNT(C) 
     FROM (VALUES(CAST(Col1 AS SQL_VARIANT)), 
         (Col2), 
         /*....*/ 
         (Col9), 
         (Col10)) T(C)) AS NumberOfNulls 
FROM Customer 
0

Tùy thuộc vào những gì bạn muốn làm, và nếu bạn bỏ qua mavens, và nếu bạn sử dụng SQL Server 2012, bạn có thể để nó một cách khác. .

Tổng số cột ứng cử viên ("vị trí") phải được biết. 1. Chọn tất cả các cột "vị trí" đã biết theo cột (chúng được biết). 2. Bỏ trục kết quả để có được một bảng với một hàng cho mỗi cột ban đầu. Điều này hoạt động vì các cột trống không bỏ ghim và bạn biết tất cả các tên cột. 3. Đếm (*) kết quả để có được số lượng không null; trừ từ đó để nhận câu trả lời của bạn.

Như thế này, đối với 4 "ghế" trong một chiếc xe

select 'empty seats' = 4 - count(*) 
from 
(
    select carId, seat1,seat2,seat3,seat4 from cars where carId = @carId 
) carSpec 
unpivot (FieldValue FOR seat in ([seat1],[seat2],[seat3],[seat4])) AS results 

này rất hữu ích nếu bạn có thể cần phải làm nhiều hơn nữa chậm nhất là chỉ cần đếm số cột không null, vì nó cung cấp cho bạn một cách để thao tác các cột như một tập hợp quá.

0

Điều này sẽ cung cấp cho bạn số cột không rỗng.bạn có thể áp dụng điều này một cách thích hợp

SELECT ISNULL(COUNT(col1),'') + ISNULL(COUNT(col2),'') +ISNULL(COUNT(col3),'') 
    FROM TABLENAME 
    WHERE ID=1 
+0

Nói đúng, 'ISNULL()' là không bắt buộc, vì 'COUNT (*)' trả về một giá trị.Lưu ý rằng 'ISNULL()' không hiện diện trên mọi hệ thống, và OP không bao giờ xác định những gì RDBMS mà anh ta đang sử dụng, có nghĩa là câu trả lời có thể không có tác dụng với anh ta. Và cuối cùng ... nếu 'COUNT()' bằng cách nào đó _did_ trả về một giá trị null, thực tế là bạn đang trả về một ** blank ** sẽ gây ra lỗi này; hoặc bạn nhận được một chuỗi ký tự thay vì tổng số, hoặc DB phàn nàn về loại không phù hợp. Cho rằng, và thực tế câu hỏi là gần 2 tuổi với một câu trả lời được chấp nhận, -1 (ý tưởng cơ bản hoạt động mặc dù) –

1

Đối ORACLE chỉ -DBMS.

Bạn có thể sử dụng NVL2 chức năng:

NVL2(string1, value_if_not_null, value_if_null) 

Đây là một lựa chọn với một cách tiếp cận tương tự như Michael Berkowski gợi ý:

SELECT (NVL2(col1, 0, 1) 
     + NVL2(col2, 0, 1) 
     + NVL2(col3, 0, 1) 
     ... 
     ... 
     + NVL2(col10, 0, 1) 
     ) AS sum_of_nulls 
FROM table 
WHERE Customer=some_cust_id 

Một cách tiếp cận chung chung hơn sẽ được để viết một PL/SQL-block và sử dụng SQL động. Bạn phải tạo chuỗi CHỌN bằng phương pháp NVL2 từ trên cho mỗi cột trong all_tab_columns của một bảng cụ thể.

0

Tập lệnh dưới đây cung cấp cho bạn số lượng giá trị NULL trong một hàng tức là số cột không có giá trị.

{SELECT 
    *, 
    (SELECT COUNT(*) 
    FROM (VALUES (Tab.Col1) 
       ,(Tab.Col2) 
       ,(Tab.Col3) 
       ,(Tab.Col4)) InnerTab(Col) 
     WHERE Col IS NULL) NullColumnCount 
FROM (VALUES(1,2,3,4) 
      ,(NULL,2,NULL,4) 
      ,(1,NULL,NULL,NULL)) Tab(Col1,Col2,Col3,Col4) } 

Chỉ để chứng minh tôi đang sử dụng bảng nội tuyến trong ví dụ của mình.

Cố gắng truyền hoặc chuyển đổi tất cả các giá trị cột thành một loại phổ biến, nó sẽ giúp bạn so sánh cột thuộc loại khác nhau.

+0

Tôi không quen thuộc với "InnerTab". Tôi googled nó và không thể tìm thấy một định nghĩa. Ai đó có thể cung cấp một đầu mối cho tôi như những gì điều này có nghĩa? –

0

tôi đã không kiểm tra nó, nhưng tôi cố gắng làm điều đó bằng cách sử dụng SQL chức năng PL \

CREATE OR REPLACE TYPE ANYARRAY AS TABLE OF ANYDATA 
; 

CREATE OR REPLACE Function COUNT_NULL 
(ARR IN ANYARRAY) 
RETURN number 
IS 
    cnumber number ; 
BEGIN 

    for i in 1 .. ARR.count loop 
    if ARR(i).column_value is null then 
     cnumber := cnumber + 1; 
    end if; 
    end loop; 

RETURN cnumber; 

EXCEPTION 
WHEN OTHERS THEN 
    raise_application_error 
    (-20001,'An error was encountered - ' 
    ||SQLCODE||' -ERROR- '||SQLERRM); 
END 
; 

Sau đó, sử dụng nó trong một truy vấn chọn như thế này

CREATE TABLE TEST (A NUMBER, B NUMBER, C NUMBER); 

INSERT INTO TEST (NULL,NULL,NULL); 
INSERT INTO TEST (1 ,NULL,NULL); 
INSERT INTO TEST (1 ,2 ,NULL); 
INSERT INTO TEST (1 ,2 ,3 ); 

SELECT ROWNUM,COUNT_NULL(A,B,C) AS NULL_COUNT FROM TEST; 

dự kiến sản lượng

ROWNUM | NULL_COUNT 
-------+----------- 
    1 | 3 
    2 | 2 
    3 | 1 
    4 | 0 
0

Đây là cách tôi đã cố gắng

CREATE TABLE #temptablelocal (id int NOT NULL, column1 varchar(10) NULL, column2 varchar(10) NULL, column3 varchar(10) NULL, column4 varchar(10) NULL, column5 varchar(10) NULL, column6 varchar(10) NULL); 


INSERT INTO #temptablelocal 
VALUES (1, 
     NULL, 
     'a', 
     NULL, 
     'b', 
     NULL, 
     'c') 
SELECT * 
FROM #temptablelocal 
WHERE id =1 
    SELECT count(1) countnull 
    FROM 
    (SELECT a.ID, 
      b.column_title, 
      column_val = CASE b.column_title  
      WHEN 'column1' THEN a.column1 
      WHEN 'column2' THEN a.column2 
      WHEN 'column3' THEN a.column3 
      WHEN 'column4' THEN a.column4 
      WHEN 'column5' THEN a.column5 
      WHEN 'column6' THEN a.column6 
      END 
    FROM 
     (SELECT id, 
       column1, 
       column2, 
       column3, 
       column4, 
       column5, 
       column6 
     FROM #temptablelocal 
     WHERE id =1) a 
    CROSS JOIN 
     (SELECT 'column1' 
     UNION ALL SELECT 'column2' 
     UNION ALL SELECT 'column3' 
     UNION ALL SELECT 'column4' 
     UNION ALL SELECT 'column5' 
     UNION ALL SELECT 'column6') b (column_title)) AS pop WHERE column_val IS NULL 
    DROP TABLE #temptablelocal 

enter image description here

Các vấn đề liên quan