Ela*_* L. 7 t-sql sql-server sql-server-2012
我想计算NULL一行中的值的数量.
例如:
Name Col1 Col2 Col3 Col4 | ansCol
abc null a@c.com null null | 3
bbc null null null null | 4
Run Code Online (Sandbox Code Playgroud)
在这个例子中,答案很简单:
SELECT *,
(CASE WHEN Name IS NULL THEN 1 ELSE 0 END +
CASE WHEN Col1 IS NULL THEN 1 ELSE 0 END +
CASE WHEN Col2 IS NULL THEN 1 ELSE 0 END +
CASE WHEN Col3 IS NULL THEN 1 ELSE 0 END +
CASE WHEN Col4 IS NULL THEN 1 ELSE 0 END) as ansCol
Run Code Online (Sandbox Code Playgroud)
当我们有一个非常宽的表,超过10列时,问题变得更加复杂.如果我尝试使用显示的方法,我会收到以下错误:
消息125,级别15,状态4,行13个案例表达式只能嵌套到级别10.
有没有办法克服这个问题?
你的问题中的代码没有任何嵌套的情况,所以你应该能够将10个以上的链接加起来就好了.
但其他一些可能性......
如果所有列都具有相同的数据类型,则可以使用(Demo)
SELECT *,
ansCol = (SELECT COUNT(*) - COUNT(C) FROM (VALUES(c1),(c2),(c3),(c4)) V(C))
FROM t1
Run Code Online (Sandbox Code Playgroud)
或者另一种不依赖于它们具有相同数据类型的替代方案.
;WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' as ns)
SELECT *,
ansCol = (SELECT x.* FOR XML PATH('row'),
ELEMENTS XSINIL, TYPE).value('count(/row/*[@ns:nil])', 'int')
FROM t1 x
Run Code Online (Sandbox Code Playgroud)
除了上述之外,一种潜在的方法是使用PIVOT和UNPIVOT功能。
让我们首先创建表并根据问题插入数据:
/* Create table */
CREATE TABLE so_40957006 (
[name] VARCHAR(24),
[col1] VARCHAR(24),
[col2] VARCHAR(24),
[col3] VARCHAR(24),
[col4] VARCHAR(24)
)
/* Insert data */
INSERT INTO so_40957006 VALUES('abc', null, 'a@c.com', null, null)
INSERT INTO so_40957006 VALUES('bbc', null, null, null, null)
Run Code Online (Sandbox Code Playgroud)
我们首先要做的是创建一个身份表,这样我们就可以唯一地标识每一行数据并插入数据。
/* Create identity table */
CREATE TABLE so_40957006_id (
[lid] INT IDENTITY(1, 1),
[name] VARCHAR(24),
[col1] VARCHAR(24),
[col2] VARCHAR(24),
[col3] VARCHAR(24),
[col4] VARCHAR(24)
)
/* Insert data into table */
INSERT INTO so_40957006_id
SELECT
ISNULL([name], 1) AS [name]
,ISNULL([col1], 1) AS [col1]
,ISNULL([col2], 1) AS [col2]
,ISNULL([col3], 1) AS [col3]
,ISNULL([col4], 1) AS [col4]
FROM so_40957006
Run Code Online (Sandbox Code Playgroud)
请注意,在此过程中,我们已使用 将任何为 null 的列转换为值 1 IsNull。该表现在如下所示。
lid name col1 col2 col3 col4
1 abc 1 a@c.com 1 1
2 bbc 1 1 1 1
Run Code Online (Sandbox Code Playgroud)
有了这个,我们现在可以使用PIVOT和UNPIVOT来垂直化数据。例如,运行下面的查询
SELECT [lid], [cols], [val]
FROM
(SELECT [lid], [name], [col1], [col2], [col3], [col4]
FROM so_40957006_id) p
UNPIVOT
(val FOR cols IN
([name], [col1], [col2], [col3], [col4])
) AS unpvt
Run Code Online (Sandbox Code Playgroud)
为您提供垂直输出:
lid cols val
1 name abc
1 col1 1
1 col2 a@c.com
1 col3 1
1 col4 1
2 name bbc
2 col1 1
2 col2 1
2 col3 1
2 col4 1
Run Code Online (Sandbox Code Playgroud)
由于您要计数的值(即NULLs)的值为 1,因此您只需运行GROUP BY+SUM语句即可:
SELECT [lid], SUM(cast([val] as integer)) as CountNulls
FROM (
SELECT [lid], [cols], [val]
FROM
(SELECT [lid], [name], [col1], [col2], [col3], [col4]
FROM so_40957006_id) p
UNPIVOT
(val FOR cols IN
([name], [col1], [col2], [col3], [col4])
) AS unpvt
) a
WHERE ISNUMERIC([val]) = 1
GROUP BY [lid]
Run Code Online (Sandbox Code Playgroud)
与输出
lid CountNulls
1 3
2 4
Run Code Online (Sandbox Code Playgroud)
[lid]您可以将此JOIN输出返回到原始表以生成结果集。
| 归档时间: |
|
| 查看次数: |
185 次 |
| 最近记录: |