2011-12-21 4 views
18

Мне было интересно узнать счетчик нулевых столбцов строки в SQL, у меня есть таблица Customer с нулевыми значениями, просто мне нужен запрос, который возвращает int числа нулевых столбцов для определенной строки (определенный клиент).Подсчитайте нулевые столбцы в строке в SQL

+0

Это не то, что вы должны хотеть сделать в SQL – zerkms

+0

Для моего собственного любопытства, почему вы хотите это знать? – UnhandledExcepSean

+0

Какие РСУБД? Какие столбцы? Все ли они одного типа данных? –

ответ

27

Этот метод назначает 1 или 0 для нулевых столбцов и добавляет их все вместе. Надеюсь, вы не слишком много NULLABLE столбцов, чтобы добавить здесь ...

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 

Примечания, вы также можете сделать это, возможно, немного более синтаксически чисто с IF(), если ваша СУБД поддерживает его.

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 

Я проверил этот шаблон на столе и, похоже, работает нормально.

+0

'IF()' может выглядеть синтаксически чище, но 'CASE' более универсально поддерживается. Тем не менее, для продолжения этой строки, с самого универсального решения до самого чистого, я бы предложил следующее: «SELECT ((col1 IS NULL) + (col2 IS NULL) + ...) AS sum_of_nulls FROM ...'. –

+0

Как считать это? –

+1

@ImanMarashi Я не уверен, что вы просите. Результатом этого запроса является одиночный целочисленный столбец, представляющий количество столбцов NULL для каждой строки. –

-1

Существует не простой способ сделать это, как если бы было с подсчетом строк. В принципе, вам нужно перечислить все столбцы, которые могут быть пустыми в одном выражении.

Таким образом, для таблицы с возможно нулевыми столбцами a, b,c, вы можете сделать это:

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

Это не сработает. Если a, b, c не являются числовыми, это вызовет ошибку. Если они являются числовыми, это вернет неправильные результаты. –

0

К сожалению, в стандартном заявлении SQL вы должны ввести каждый столбец, который вы хотите проверить, чтобы проверить все программно вы можете использовать T-SQL. Предупреждение, однако, убедитесь, что вы работаете с подлинными NULLS, вы можете иметь пустые хранимые значения, которые база данных не будет распознавать как истинный NULL (я знаю, это звучит странно).

Вы можете избежать этого, захватывая пустые значения и NULLS в заявлении, как это:

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

Или в некоторых базах данных, таких как Oracle (не уверен, что если есть какие-либо другие) вы будете использовать:

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

Вы не указываете СУРБД. Для 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

В зависимости от того, что вы хотите сделать, и если вы игнорируете знаток, и если вы используете SQL Server 2012, вы можете к нему другому способу. ,

Общее количество столбцов-кандидатов («слоты») должно быть известно. 1. Выберите все известные столбцы «слоты» по столбцам (они известны). 2. Не удалите этот результат, чтобы получить таблицу с одной строкой на исходный столбец. Это работает, потому что в нулевых столбцах нет univot, и вы знаете все имена столбцов. 3. Считать (*) результат, чтобы получить количество ненулевых значений; вычтите из этого, чтобы получить ответ.

Как это, на 4 «мест» в автомобиле

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 

Это полезно, если вы, возможно, потребуется сделать более позднее, чем просто подсчитать количество ненулевых столбцов, поскольку это дает вам способ также манипулировать столбцами как набор.

0

Это даст вам количество столбцов, которые не равны нулю.Вы можете применить это правильно

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

Строго говоря, 'ISNULL()' не требуется, поскольку 'COUNT (*)' возвращает значение.Обратите внимание, что 'ISNULL()' не присутствует в каждой системе, и OP никогда не указывал, какие RDBMS он использовал, то есть ответ, возможно, и не сработал для него. И, наконец ... если 'COUNT()' somehow_did_ возвращает null, тот факт, что вы возвращаете ** пробел **, приведет к сбою; либо вы получаете строку символов вместо общего, либо БД жалуется на несоответствия типов. Для этого и тот факт, что вопрос составляет почти 2 года с принятым ответом, -1 (основная идея работает, хотя) –

1

Для ORACLE -DBMS только.

Вы можете использовать NVL2 функцию:

NVL2(string1, value_if_not_null, value_if_null) 

Вот отборное с похож подход, как предложил Майкл Берковский:

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 

Более общий подход был бы написать PL/SQL-блок и использовать динамический SQL. Вы должны построить строку SELECT с помощью метода NVL2 сверху для каждого столбца в таблице all_tab_columns конкретной таблицы.

0

Нижеприведенный скрипт дает вам значение NULL в строке, то есть, сколько столбцов не имеет значений.

{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) } 

Просто, чтобы продемонстрировать, что я использую встроенный стол в моем примере.

Попробуйте применить или преобразовать все значения столбцов в общий тип, это поможет вам сравнить столбец разного типа.

+0

Я не знаком с «InnerTab». Я искал ее и не могу найти определение. Может ли кто-нибудь дать мне понять, что это значит? –

0

Я не проверял, но я хотел бы попробовать сделать это с помощью PL \ SQL функции

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 
; 

Затем использовать его в запросе на выборку, как этот

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; 

Ожидаемое выход

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

Это, как я пытался

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

Смежные вопросы