在SQL中连续计算Null列

时间:2011-12-21 21:18:22

标签: sql

我想知道在SQL中计算行的空列的可能性,我有一个表具有可空值的表Customer,我只想要一个返回某行的空列数的int的查询(某些客户) )。

13 个答案:

答案 0 :(得分:33)

此方法为空列分配1或0,并将它们全部添加在一起。希望你没有太多可以为空的列添加到这里......

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

注意,如果您的RDBMS支持它,您也可以使用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

我在桌子上测试了这种模式,看起来它可以正常工作。

答案 1 :(得分:3)

我的答案建立在Michael Berkowski's answer之上,但为了避免输入数百个列名,我所做的就是:

第1步:获取表格中所有列的列表

Ext.Msg.alert('Name', 'Please enter your name:', function(btn, text){
    if (btn == 'ok'){
        console.log("OK clicked");
        // you code here
    }
});

步骤2:将该列表粘贴到Notepad ++中(任何支持正则表达式替换的编辑器都可以使用)。然后使用此替换模式

  • 搜索:

       Public Sub Main()
    
        Dim filePath As String = Dts.Variables("User::filepath").Value.ToString()
    
        Dim content As String = File.ReadAllText(filePath).Replace("}", "},")
        content = content.Substring(0, Len(content) - 1)
        content = "{ ""query"" : [" + content + "] }"
        File.WriteAllText(filePath, content)
        Dts.TaskResult = ScriptResults.Success
    End Sub
    
  • 替换:

    SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'myTable';
    

第3步:前置^(.*)$ 并将最后\(CASE WHEN \1 IS NULL THEN 1 ELSE 0 END\) + 更改为SELECT identityColumnName,,并可选择添加+

AS NullCount FROM myTable

答案 2 :(得分:1)

仅适用于 ORACLE -DBMS。

您可以使用NVL2功能:

NVL2( string1, value_if_not_null, value_if_null )

这是Michael Berkowski建议采用类似方法的选择:

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。您必须使用上面的 NVL2 方法为特定表的 all_tab_columns 中的每一列构建一个SELECT字符串。

答案 3 :(得分:0)

不幸的是,在标准的SQL语句中,您必须输入要测试的每个列,以编程方式测试所有可以使用T-SQL的列。但是请注意,确保您正在使用真正的NULLS,您可以使用空白存储的值,数据库将无法将其识别为真NULL(我知道这听起来很奇怪)。

您可以通过在以下语句中捕获空白值和NULLS来避免这种情况:

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

或者在某些数据库(例如Oracle(不确定是否还有其他数据库)中,您将使用:

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

答案 4 :(得分:0)

您不会声明RDBMS。对于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  

答案 5 :(得分:0)

取决于您想要做什么,如果您忽略了专家,并且您使用SQL Server 2012,您可以采用另一种方式。

必须知道候选列(“插槽”)的总数。  1.逐列选择所有已知的“槽”(它们是已知的)。  2.取消结果得到一个     每个原始列有一行的表。这是有效的,因为空列不行     unpivot,你知道所有的列名。  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

如果您可能需要更多时间而不仅仅计算非空列的数量,这非常有用,因为它为您提供了将列作为集合进行操作的方法。

答案 6 :(得分:0)

这将为您提供非空的列数。你可以适当地应用这个

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

答案 7 :(得分: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) } 

只是为了演示我在我的例子中使用内联表。

尝试将所有列值转换或转换为常用类型,它将帮助您比较不同类型的列。

答案 8 :(得分: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

答案 9 :(得分: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

答案 10 :(得分:0)

类似,但动态:

drop table if exists myschema.table_with_nulls;

create table myschema.table_with_nulls as

select 
   n1::integer,
   n2::integer,
   n3::integer,
   n4::integer,
   c1::character varying,
   c2::character varying,
   c3::character varying,
   c4::character varying
from 
   (
      values 
         (1,2,3,4,'a','b','c','d'),
         (1,2,3,null,'a','b','c',null),
         (1,2,null,null,'a','b',null,null),
         (1,null,null,null,'a',null,null,null)
   ) as test_records(n1, n2, n3, n4, c1, c2, c3, c4);


drop function if exists myschema.count_nulls(varchar,varchar);

create function myschema.count_nulls(schemaname varchar, tablename varchar) returns void as 
$BODY$
   declare
      calc varchar;
      sqlstring varchar;
begin
   select
      array_to_string(array_agg('(' || trim(column_name) || ' is null)::integer'),' + ') 
   into
      calc
   from
      information_schema.columns
   where 
      table_schema in ('myschema') 
         and table_name in ('table_with_nulls'); 

   sqlstring = 'create temp view count_nulls as select *, ' || calc || '::integer as count_nulls from myschema.table_with_nulls';

   execute sqlstring;

   return;
end;
$BODY$ LANGUAGE plpgsql STRICT;

select * from myschema.count_nulls('myschema'::varchar,'table_with_nulls'::varchar);


select
   *
from 
   count_nulls;

虽然我发现我没有完成功能的参数化。

答案 11 :(得分:0)

我的答案建立在Drew Chapin's answer的基础上,但是避免了分步执行该过程而只在单个查询中执行的情况:

use <add_database_here>;
Declare @val Varchar(MAX); 

Select @val = COALESCE(@val + str, str) From 
    (SELECT
    '(CASE WHEN '+COLUMN_NAME+' IS NULL THEN 1 ELSE 0 END) +' str
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<add table name here>'
    ) t1 -- getting column names and adding the case when to replace NULLs for zeros or ones

Select @val = SUBSTRING(@val,1,LEN(@val) - 1) -- removing trailling add sign

Select @val = 'SELECT <add_identity_column_here>, ' + @val + ' AS NullCount FROM <add table name here>' -- adding the 'select' for the column identity, the 'alias' for the null count column, and the 'from'

EXEC (@val) --executing the resulting sql

答案 12 :(得分:-1)

没有一种简单的方法可以像计算行一样。基本上,您必须枚举一个表达式中可能为null的所有列。

因此对于可能为空列ab, c的表,您可以这样做:

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