查询表中每列的已填充行数(SQL Server)
我试图为表中的每一列获取非空值计数。我已经研究了之前提出的以下问题,但没有找到令人满意的答案: 我编写了以下代码,试图为我的表构建一个数据字典,其中包括列的名称、每列中填充的行数、数据类型、长度以及它是否是主键:查询表中每列的已填充行数(SQL Server),sql,sql-server,tsql,Sql,Sql Server,Tsql,我试图为表中的每一列获取非空值计数。我已经研究了之前提出的以下问题,但没有找到令人满意的答案: 我编写了以下代码,试图为我的表构建一个数据字典,其中包括列的名称、每列中填充的行数、数据类型、长度以及它是否是主键: SELECT c.name 'Column Name', p.rows 'Row_Count', t.Name 'Data type', c.max_length 'Max Length', ISNULL(i.is_primary_key
SELECT
c.name 'Column Name',
p.rows 'Row_Count',
t.Name 'Data type',
c.max_length 'Max Length',
ISNULL(i.is_primary_key, 0) 'Primary Key'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN
sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
LEFT OUTER JOIN
sys.partitions p ON p.OBJECT_ID = i.OBJECT_ID and i.index_id = p.index_id
WHERE
c.object_id = OBJECT_ID('my_table')
但是,Row_Count列返回所有空值
我的预期结果如下所示:
Column_Name Row_Count Data_Type Max_Length Primary_Key
A 10 varchar 50 0
B 10 varchar 50 0
C 7 float 50 0
D 3 float 50 0
E 10 varchar 50 0
这里有一个不使用动态SQL的选项 全面披露,我怀疑DS的表现会更好。也就是说,这将适用于几乎任何表、视图或查询。我正在使用
master..spt\u值作为演示
示例
Select ColumnName = Item
,B.column_ordinal
,Row_Count = sum(1)
,B.system_type_name
,B.max_length
,Distinct_Values = count(DISTINCT Value)
From (
Select C.*
From master..spt_values A
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
Cross Apply (
Select Item = replace(xAttr.value('local-name(.)', 'varchar(100)'),'_x0020_',' ')
,Value = xAttr.value('.','varchar(max)')
From XMLData.nodes('//@*') xNode(xAttr)
) C
) A
Left Join (
Select * from sys.dm_exec_describe_first_result_set('Select * from master..spt_values',null,null )
) B on A.Item=B.name
Group By A.Item
,B.system_type_name
,B.max_length
,B.column_ordinal
Order By B.column_ordinal
返回
编辑
正如Larnu提到的,(var)binary和image会失败。同样,这在大桌子上也不会很好地执行。我只是在发现阶段才使用过这种方法。天哪,这太难看了
DECLARE @SQL nvarchar(MAX);
DECLARE @Table sysname = 'SampleTable';
DECLARE @Schema sysname = 'dbo';
SET @SQL = N'WITH Counts AS (' + NCHAR(13) + NCHAR(10) +
N' SELECT @Schema AS SchemaName,' + NCHAR(13) + NCHAR(10) +
N' @Table AS TableName,' +
STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
N' COUNT(' + QUOTENAME(C.COLUMN_NAME) + N') AS ' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_SCHEMA = @Schema
AND C.TABLE_NAME = @Table
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,14,N'') + NCHAR(13) + NCHAR(10) +
N' FROM ' + QUOTENAME(@Table) + N')' + NCHAR(13) + NCHAR(10) +
N'SELECT V.ColumnName,' + NCHAR(13) + NCHAR(10) +
N' V.NonNullCount,' + NCHAR(13) + NCHAR(10) +
N' ISC.DATA_TYPE + ISNULL(DT.S,'''') AS Datatype,' + NCHAR(13) + NCHAR(10) +
N' ISNULL(PK.IsPrimaryKey,''No'') AS PrimaryKey' + NCHAR(13) + NCHAR(10) +
N'FROM Counts C' + NCHAR(13) + NCHAR(10) +
N' CROSS APPLY(VALUES' + STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
N' (N' + QUOTENAME(C.COLUMN_NAME,'''') + N',C.' + QUOTENAME(C.COLUMN_NAME) + N')'
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_NAME = @Table
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,26,N'') + N')V(ColumnName,NonNullCount)' + NCHAR(13) + NCHAR(10) +
N' JOIN INFORMATION_SCHEMA.COLUMNS ISC ON C.SchemaName = ISC.TABLE_SCHEMA' + NCHAR(13) + NCHAR(10) +
N' AND C.TableName = ISC.TABLE_NAME' + NCHAR(13) + NCHAR(10) +
N' AND V.ColumnName = ISC.COLUMN_NAME' + NCHAR(13) + NCHAR(10) +
N' CROSS APPLY (VALUES(''('' + STUFF(CONCAT('','' + CASE ISC.CHARACTER_MAXIMUM_LENGTH WHEN -1 THEN ''MAX'' ELSE CONVERT(varchar(4),ISC.CHARACTER_MAXIMUM_LENGTH) END,' + NCHAR(13) + NCHAR(10)+
N' '','' + CASE WHEN ISC.DATA_TYPE NOT LIKE ''%int'' THEN CONVERT(varchar(4),ISC.NUMERIC_PRECISION) END,' + NCHAR(13) + NCHAR(10) +
N' '','' + CASE WHEN ISC.DATA_TYPE NOT LIKE ''%int'' THEN CONVERT(varchar(4),ISC.NUMERIC_SCALE) END,' + NCHAR(13) + NCHAR(10) +
N' '','' + CONVERT(varchar(4),ISC.DATETIME_PRECISION)),1,1,'''') + '')'')) DT(S)' + NCHAR(13) + NCHAR(10) +
N' OUTER APPLY(SELECT ''Yes'' AS IsPrimaryKey ' + NCHAR(13) + NCHAR(10) +
N' FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC' + NCHAR(13) + NCHAR(10) +
N' JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON TC.TABLE_SCHEMA = KCU.TABLE_SCHEMA' + NCHAR(13) + NCHAR(10) +
N' AND TC.TABLE_NAME = KCU.TABLE_NAME' + NCHAR(13) + NCHAR(10) +
N' AND TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME' + NCHAR(13) + NCHAR(10) +
N' WHERE TC.CONSTRAINT_TYPE = ''PRIMARY KEY''' + NCHAR(13) + NCHAR(10) +
N' AND KCU.COLUMN_NAME = V.ColumnName' + NCHAR(13) + NCHAR(10) +
N' AND TC.TABLE_SCHEMA = ISC.TABLE_SCHEMA' + NCHAR(13) + NCHAR(10) +
N' AND TC.TABLE_NAME = ISC.TABLE_NAME) PK;';
PRINT @SQL; --Might need to use SELECT here
--SELECT @SQL;
EXEC sp_executesql @SQL, N'@Schema sysname,@Table sysname',@Schema = @Schema, @Table = @Table;
老实说,这里发生了很多事情。如果需要解释,我会尝试,但这需要一些时间,因此(没有冒犯),如果没有人想/需要知道,我不会付出努力
值得注意的是,我有点懒,没有加入SCHEMA\u NAME
。如果您使用多个模式和相同的命名对象,这将有问题,需要解决
编辑:显然我是一个贪吃的惩罚。修复了模式“问题”,并添加了一些关于INT的逻辑
AFAIK,没有一个系统视图/函数可以告诉您一列有多少个非空值。您必须使用动态SQL对每一列进行计数(列)
。您希望如何获取数据?每列1列,或每列2列(列名和计数)和一行?我的预期结果是第一列中的列名,第二列中填充行的计数,第三列中的数据类型,第四列中的数据长度,以及第五列中的主键是否是真正重要的信息,我认为你需要向我们展示你在问题中想要的结果集。这远远不止“我正在尝试为我的表中的每一列获取非null值的计数”,您可以从系统表中检查可空性,如果该列不允许为null,则使用元数据中的行计数,但如果该表中有任何允许为null的列,则必须查询该表以获取这些列的计数,这样就可以了,但它并没有返回我所有专栏的结果,只是其中的一部分——真的不知道出了什么问题here@thedatasleuth您是否调整了sys.dm_exec_descripe_first_result_set(“…”)?是的,我在两个位置都调整了表名-奇怪的是,对于返回的列,一切都很完美。有没有想过为什么会跳过某些列?@thedatasleuth是否有些列完全为空?如果是这样的话,除非将其设置为外部joinOne注释,否则它们将被排除,如果表包含(var)二进制
或图像
数据类型,则此操作将失败。我也明白你所说的表演是什么意思;面对一张大桌子,它确实显得很挣扎(至少在我的小家用电脑上)。尽管如此,我还是在精心照料中看到了美。老实说,我认为这花了我太长时间呵呵