计算 SQL Server 2012 中每行大于 0 的列数

Counting the number of columns greater than 0 for each row in SQL Server 2012

我有一个包含 150 多列的 table。有什么方法可以为每个客户动态计算大于 0 的列。

table 视图如下:

     CustomerID  (SomeColumns)    Column1       Column2 ------------------ Column150
         1           -----           0            12        0  33  0  18       97
         2           -----           1             0        54  0  72  0        0
         .
         .
         .

这个 table 有 50 万行。 column1 到 column150 的值要么是 0,要么不是。如何计算大于 0 的列数?

查询:

Update Table
set NumOfColumnsGreaterThanZero = (select Sum(case when Column1 to Column150 >0 then 1 else 0 end)

您可以根据 sys.columns 创建动态 SQL,例如:

declare @columns varchar(8000), @sql varchar(8000)

set @columns = ''

select @columns = @columns + 'case when [' + name + '] > 0 then 1 else 0 end+'
from sys.columns 
where 
    object_id = object_id('TABLENAME') and 
    name not in ('not','wanted','columns') and 
    user_type_id in (select user_type_id from sys.types where name = 'int')


set @sql = 'select CustomerId, ' + @columns + '0 as VALUE from TABLENAME'
exec (@sql)

当然,这种方法存在风险,即向 table 添加新列可能会导致不需要的结果。

这是一个在临时 table 上使用 3 列的基本示例。您可以使用 Dynamic SQL.

为您的结构调整它

示例数据:

CREATE TABLE #Customers
(
    CustomerID INT
    , SomeColumn VARCHAR(100)
    , Column1 INT
    , Column2 INT
    , Column3 INT
);


INSERT INTO #Customers
    (CustomerID, SomeColumn, Column1, Column2, Column3)
VALUES
    (1, 'aaa', 1, 0, 2)
    , (2, 'bbb', 0, 0, 3)
    , (3, 'ccc', 0, 0, 0)

实际查询:

SELECT CustomerID, SomeColumn, IIF(Column1 > 0, 1, 0) + IIF(Column2 > 0, 1, 0) + IIF(Column3 > 0, 1, 0) AS T
FROM #Customers

结果如下所示:

CustomerID  SomeColumn  T
1           aaa         2
2           bbb         1
3           ccc         0

我怀疑你有 150 列的正当理由。然而,这里是如何使用 Pivot 计算非 0 的值:

DECLARE @table TABLE(customer_id int, col1 int, col2 int, 
                     col3 int, col4 int, col5 int);  

INSERT INTO @table
VALUES(1, 1, 2, 3, 4, 5) ,(2, 0, 2, 0, 4, 5) 

SELECT count(CASE WHEN columns <> 0 THEN 1 END), customer_id
FROM @table as p  
UNPIVOT      
(columns FOR Seq IN           
([col1], [col2], [col3], [col4], [col5]) ) AS unpvt  
GROUP BY customer_id

结果:

5   1
3   2

如果您想 select 动态列:

CREATE TABLE 
  test_table(customer_id int, col1 int, col2 int,
             col3 int, col4 int, col5 int);  

INSERT INTO test_table
VALUES(1, 1, 2, 3, 4, 5) ,(2, 0, 2, 0, 4, 5) ;

DECLARE @columnnames varchar(max)
SELECT @columnnames = coalesce(@columnnames + ',['+ column_name + ']' , '['+ column_name + ']' )
FROM INFORMATION_SCHEMA.Columns 
WHERE
  table_name = 'test_table' and 
  column_name like 'col[0-9]%' and
  table_schema = 'dbo'
ORDER BY column_name

DECLARE @sql varchar(max) = 
'SELECT count(CASE WHEN columns <> 0 THEN 1 END), customer_id
FROM test_table as p  
UNPIVOT      
(columns FOR Seq IN           
('+@columnnames+') ) AS unpvt  
GROUP BY customer_id'

EXEC (@sql)

为了避免我误解你的问题,我尝试创建样本table和数据,基本上我从你的问题中了解到的是,每一列都是整数类型,只要记录大于0则设置为 1,否则为 0;如果您能够提供示例数据和预期输出,这很好。 :)

CREATE TABLE tblTEST
(
COLUMN1 INT,
COLUMN2 INT,
COLUMN3 INT,
COLUMN4 INT,
COLUMN5 INT
)

INSERT INTO tblTEST
SELECT 1,0,5,12,6
UNION ALL
SELECT 1,10,0,12,6
UNION ALL
SELECT 1,30,5,0,6

DECLARE @ColumnName NVARCHAR(MAX) = ''
DECLARE @Table_Name NVARCHAR(1000) = 'TBLTEST'
DECLARE @Query NVARCHAR(MAX) = ''

DECLARE @nStart INT = 1
DECLARE @nLast INt = (SELECT COUNT(1) FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @Table_Name )

WHILE @nStart <=@nLast
BEGIN

SET @ColumnName = @ColumnName + ' CASE WHEN '+  (SELECT COLUMN_NAME FROM(SELECT COLUMN_NAME,ROW_NUMBER() OVER(ORDER BY COLUMN_NAME) RN FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @Table_Name) T1 WHERE RN=@nStart) + ' >0 THEN 1 ELSE 0 END '+ (SELECT COLUMN_NAME FROM(SELECT COLUMN_NAME,ROW_NUMBER() OVER(ORDER BY COLUMN_NAME) RN FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @Table_Name) T1 WHERE RN=@nStart) + ','

SET @nStart = @nStart + 1
END

SET @ColumnName = SUBSTRING(@ColumnName,1,LEN(@ColumnName)-1)

SET @Query = 'SELECT ' + @ColumnName + ' FROM ' + @Table_Name

EXECUTE SP_EXECUTESQL @Query

另一种选择是使用动态 sql 和 while 循环

示例数据

 -- Populate some sample data

IF OBJECT_ID('tempdb..#T','U') IS NOT NULL DROP TABLE #T;

CREATE TABLE #T
 (Column1 INT, Column2 INT, Column3 INT, Column4 INT, Column5 INT);

INSERT INTO #T VALUES 
 (0,0,0,1,0), 
 (0,1,0,1,0), 
 (1,0,0,2,0), 
 (1,0,0,0,1);

动态 SQL 带 while 循环

DECLARE @ResultTable TABLE (HasZeroValue TINYINT);
-- Number of columns to search for zero values
DECLARE @ColumnsCount INT = 5;
-- Dynamic sql statement
DECLARE @SQL NVARCHAR(MAX);

DECLARE @i INT = 1;

WHILE @i <= @ColumnsCount
BEGIN

 SET @SQL = 'SELECT CASE COUNT(*) WHEN 0 THEN 0 ELSE 1 END FROM #T WHERE Column' + CAST(@i AS VARCHAR) + ' > 0;'; 

 INSERT @ResultTable
 EXEC sp_executesql @SQL;

 SET @i = @i + 1;

END

SELECT SUM(HasZeroValue) FROM @ResultTable;