您可以使用以下方法:
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
並使用表達式而不是*
時,它會計算此表達式非空的行。由於這與您需要的相反,我添加了100.00 -
作爲SELECT
的開頭。
對於「空檢查」,這會使邏輯更加複雜,因此我將原邏輯留在那裏並擴展它。在那裏,我實現了對數字和字符/文本數據類型的空白檢查。您可以使用您用來確定列是否爲空的邏輯輕鬆擴展日期,二進制數據等。
我還發現,在兩個變量@nullCheck
和@emptyCheck
之間保留第一個+
更簡單,因爲它是有效的SQL,可以通過這種方式啓動表達式。
我也擴展了這個陳述,所以如果可能有多個記錄與ProductId = 123
,它會顯示所有記錄中的平均值,即i。即總和除以行數。如果count(*)
將爲零,則最外面的case
表達式僅避免零除誤差。即找不到記錄ProductId = 123
。在這種情況下,返回值是null
。
當然你知道'[AdventureWorks]的模式。[Production]。[Product]',爲什麼要使用動態SQL?你是否試圖展示反規範化如何導致稀疏的人口? – Jodrell
@Jodrell我的意思是動態sql爲了獲得表中的所有字段。我們有時會在表中添加來自查詢的字段,因此我們不希望修改每個字段更改/添加的特定(百分比)查詢。 – alwaysVBNET
通過「特定產品ID的百分比之和」,是指表中所有列的百分比總和,但僅考慮具有特定產品ID的記錄(事實上應該只有一條記錄)? – FrankPl