以下查询以null百分比的形式返回每个字段的表值。我想要的是得到特定ProductID的百分比之和。另外,我想得到一个字段的百分比(在额外的列中)没有值,即=“”。有什么想法吗?
use AdventureWorks
DECLARE @TotalCount decimal(10,2), @SQL NVARCHAR(MAX)
SELECT @TotalCount = COUNT(*) FROM [AdventureWorks].[Production].[Product]
SELECT @SQL =
COALESCE(@SQL + ', ','SELECT ') +
'cast(sum (case when ' + QUOTENAME(column_Name) +
' IS NULL then 1 else 0 end)/@TotalCount*100.00 as decimal(10,2)) as [' +
column_Name + ' NULL %]
'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Product' and TABLE_SCHEMA = 'Production'
SET @SQL = 'set @TotalCount = NULLIF(@TotalCount,0)
' + @SQL + '
FROM [AdventureWorks].Production.Product'
print @SQL
EXECUTE SP_EXECUTESQL @SQL, N'@TotalCount decimal(10,2)', @TotalCount
答案 0 :(得分:1)
您可以使用以下内容:
use AdventureWorks
DECLARE @colCount int;
DECLARE @nullCheck nvarchar(max) = N'';
DECLARE @emptyCheck nvarchar(max) = N'';
DECLARE @SQL NVARCHAR(MAX);
DECLARE @KeyToCheck int = 123; -- adapt as necessary
SELECT
@nullCheck += '
+ ' + 'count(' + QUOTENAME(column_Name) + ')'
,@emptyCheck += '
+ ' +
CASE
WHEN DATA_TYPE IN('bigint', 'int', 'smallint', 'tinyint', 'bit', 'money', 'smallmoney', 'numeric', 'decimal', 'float', 'real') THEN
-- check numeric data for zero
'sum(case when coalesce(' + QUOTENAME(column_Name) + ', 0) = 0 then 1 else 0 end)'
WHEN DATA_TYPE like '%char' or DATA_TYPE like '%text' THEN
--check character data types for empty string
'sum(case when coalesce(' + QUOTENAME(column_Name) + ', '''') = '''' then 1 else 0 end)'
ELSE -- otherwise, only check for null
'sum(case when ' + QUOTENAME(column_Name) + ' IS NULL then 1 else 0 end)'
END
,@colCount =
count(*) over()
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Product' and TABLE_SCHEMA = 'Production'
;
SET @SQL = 'SELECT case when count(*) > 0 then 100.00 - (' + @nullCheck + '
) * 100.00 / ' + cast(@colCount as nvarchar(max)) + '.00 / count(*) end as null_percent
, case when count(*) > 0 then (' + @emptyCheck + '
) * 100.00 / ' + cast(@colCount as nvarchar(max)) + '.00 / count(*) end as empty_percent
FROM Production.Product
WHERE ProductID = ' + cast(@KeyToCheck as nvarchar(max))
;
print @SQL;
EXECUTE (@SQL)
我简化了您的一个表达式:您可以使用sum (case when <column> IS NULL then 1 else 0 end)
而不是count(<column>)
。将count
与表达式而不是*
一起使用时,它会计算此表达式为非null的行。由于这与您的需求相反,我添加了100.00 -
作为SELECT
的开头。
对于“空检查”,这会使逻辑变得更加复杂,因此我将原始逻辑留在那里并对其进行扩展。在那里,我实现了对数字和字符/文本数据类型空虚的检查。您可以使用您用来确定列是否为空的逻辑,轻松地扩展日期,二进制数据等。
我还发现将+
放在两个变量@nullCheck
和@emptyCheck
中会更简单,因为这是一个有效的SQL来启动表达式。
我还扩展了声明,以便如果有ProductId = 123
个可能有多条记录,它会显示所有记录的平均值,即。即总和除以行数。如果case
为零,则最外面的count(*)
表达式可以避免除零错误,即i。即找不到ProductId = 123
的记录。在这种情况下,返回值为null
。
答案 1 :(得分:0)
您可以使用AVG
功能:
SELECT AVG(CASE WHEN value IS NULL THEN 100 ELSE 0 END) AS Percents
FROM Table
<强>更新强>
这是你的脚本:
DECLARE @SQL NVARCHAR(MAX), @TABLE_NAME NVARCHAR(MAX), @TABLE_SCHEMA NVARCHAR(MAX), @PK NVARCHAR(MAX)
SET @TABLE_NAME = 'tblBigTable'
SET @TABLE_SCHEMA = 'dbo'
SET @PK = '8'
SELECT
@SQL = COALESCE(@SQL + ', ', 'SELECT ') +'AVG(CASE WHEN ' + COLUMN_NAME + ' IS NULL THEN 100 ELSE 0 END) AS [' + COLUMN_NAME +' NULL %]'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = @TABLE_SCHEMA AND
TABLE_NAME = @TABLE_NAME
SET @SQL = @SQL + ' FROM ' + @TABLE_NAME + ' WHERE pkId = ''' + @PK + ''''
print @SQL
EXECUTE SP_EXECUTESQL @SQL