我想知道是否有一种方法可以计算表中每行的填充列数。
例如,如果我有一个名为“客户”的简单表格:
**Name** **Customer** **DOB** **Order number** **Populated Columns**
ABC Ltd Jo Blogg 2/1/78 123 3
Umbrella Co A Sherman 232 2
Nike 14/5/98 1
我想要的是一个查询,它将为我提供一个额外的列,并带有一个数字,表示其中有多少列具有值。
有什么想法吗?
答案 0 :(得分:1)
可以通过对NULL(以及此类列的空字符串)进行简单检查来完成:
SELECT
[Name]
, [Customer]
, [DOB]
, [Order number]
, CASE WHEN ISNULL([Name], '') != '' THEN 1 ELSE 0 END
+ CASE WHEN ISNULL([Customer], '') != '' THEN 1 ELSE 0 END
+ CASE WHEN [DOB] IS NOT NULL THEN 1 ELSE 0 END
+ CASE WHEN [Order number] IS NOT NULL THEN 1 ELSE 0 END AS [Populated Columns]
这对于固定和已知数量的列将很好地工作。 如果从元数据中获取列列表,则这种方法可能更通用。缺点-这需要动态SQL。 以下是 SQL Server 2017 及更高版本的示例:
DECLARE @_SQL NVARCHAR(max)
DECLARE @_TableName sysname = 'Table1'
SELECT @_SQL =
'SELECT '
+ STRING_AGG(QUOTENAME(COLUMN_NAME), ',
')
+ ', '
+ STRING_AGG('
CASE WHEN ['+COLUMN_NAME+'] IS NOT NULL THEN 1 ELSE 0 END', ' +')
+ ' AS [Populated Columns]
FROM ' + QUOTENAME(MIN(TABLE_SCHEMA)) + '.' + QUOTENAME(MIN(TABLE_NAME))
FROM INFORMATION_SCHEMA.COLUMNs
WHERE TABLE_NAME = @_TableName
EXEC sys.sp_executesql @_SQL
它将生成并执行代码:
SELECT
[Col1],
[Col2],
[Col3],
CASE WHEN [Col1] IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN [Col2] IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN [Col3] IS NOT NULL THEN 1 ELSE 0 END AS [Populated Columns]
FROM [dbo].[Table1]
在较早的版本中,这种结果是可以实现的,但是可以使用其他字符串聚合解决方法,例如XML STUFF
或SQLCLR
函数...
答案 1 :(得分:1)
只需考虑共享另一种使用UNPIVOT
进行计算的方法,并假设您的表中有一个主键/身份。
declare @tmp table (id int, [Name] varchar(100), Customer varchar(100), dob datetime, orderno int)
insert into @tmp select 1, 'name1','c1',getdate(),123
insert into @tmp select 2,'name2',null,getdate(),123
insert into @tmp select 3,'name3',null,null,null
SELECT t.*,
t1.notpopulated
FROM @tmp t
INNER JOIN (SELECT 4 - Count(*) AS NotPopulated,
id
FROM
(SELECT id,
u.x,
u.y
FROM (SELECT id,
Cast([name]AS VARCHAR(100)) [name],
Cast(customer AS VARCHAR(100)) AS customer,
Cast(dob AS VARCHAR(100)) AS dob1,
Cast(orderno AS VARCHAR(100)) orderno
FROM @tmp) AS s
UNPIVOT ( [y]
FOR [x] IN ([name],
[Customer],
dob1,
[orderno]) ) u) t
GROUP BY id) t1
ON t1.id = t.id