哦,SQL,为什么你让我感到沮丧...
大家下午好,我再次陷入困境......
我有一个数据库,其中包含表单(duh)的信息,此表单可以“保存”,以便用户可以稍后返回并处理它。我需要的是找到NOT NULL字段的百分比。例如;
COL_A |COL_B |COL_C |ETC.. z %
-------------------------- z------
X | X | NULL | z 66
X | X | X | z 100
NULL | NULL | X | z 33
NULL | NULL | NULL | z 0
锦上添花?每行需要检查47列。我可能会以错误的方式解决这个问题。任何帮助/提示将不胜感激。
答案 0 :(得分:4)
您可以将CROSS APPLY
与VALUES
结合使用:
SELECT t.*, FLOOR(100 * (1.0 * sub.col)/sub.counter) AS [percentage]
FROM #tab t
CROSS APPLY (
SELECT COUNT(c), COUNT(*)
FROM (VALUES(t.col1), (t.col2), (t.col3), (t.col4), (t.col5),
(t.col6), (t.col7), (t.col8), (t.col9), (t.col10)) AS s(c)
) AS sub(col, counter)
您需要在VALUES
子句中添加最多47个cols。
的 LiveDemo
强>
修改强>
当列具有类似的数据类型或存在隐式转换时,上述解决方案可以正常工作。如果存在没有隐式转换的数据类型,它将失败(例如UNIQUEIDENTIFIER
和DATETIME
。一个快速的解决方法是用CAST(t.colx AS NVARCHAR(100))
包装每一列:
SELECT t.*, FLOOR(100 * (1.0 * sub.col)/sub.counter) AS [percentage]
FROM #tab t
CROSS APPLY (SELECT COUNT(c), COUNT(*)
FROM (VALUES
(CAST(t.col1 AS NVARCHAR(MAX))),
(CAST(t.col2 AS NVARCHAR(MAX))),
(CAST(t.col3 AS NVARCHAR(MAX))),
(CAST(t.col4 AS NVARCHAR(MAX))),
(CAST(t.col5 AS NVARCHAR(MAX))),
(CAST(t.col6 AS NVARCHAR(MAX))),
(CAST(t.col7 AS NVARCHAR(MAX))),
(CAST(t.col8 AS NVARCHAR(MAX))),
(CAST(t.col9 AS NVARCHAR(MAX))),
(CAST(t.col10 AS NVARCHAR(MAX)))
) AS s(c)) AS sub(col, counter)
的 LiveDemo2
强>
可以使用IIF/CASE
(不再需要关注数据类型):
SELECT t.*, FLOOR(100 * (1.0 * sub.col)/sub.counter) AS [percentage]
FROM #tab t
CROSS APPLY (SELECT COUNT(c), COUNT(*)
FROM (VALUES
(IIF(t.col1 IS NULL, NULL, 1)),
(IIF(t.col2 IS NULL, NULL, 1)),
(IIF(t.col3 IS NULL, NULL, 1)),
(IIF(t.col4 IS NULL, NULL, 1)),
(IIF(t.col5 IS NULL, NULL, 1)),
(IIF(t.col6 IS NULL, NULL, 1)),
(IIF(t.col7 IS NULL, NULL, 1)),
(IIF(t.col8 IS NULL, NULL, 1)),
(IIF(t.col9 IS NULL, NULL, 1)),
(IIF(t.col10 IS NULL, NULL, 1))
) AS s(c)) AS sub(col, counter);
的 LiveDemo3
强>
答案 1 :(得分:1)
您可以让收集数据的应用程序计算未完成的行并将其与记录一起保存。您还可以创建一个计算字段,以便在保存记录时自动存储保存的百分比值。
3列示例:
CREATE TABLE [dbo].[Table](
[ID] [int] IDENTITY(1,1) NOT NULL,
[COL_A] [varchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[COL_B] [nchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[COL_C] [nchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[PctSaved] AS
((case when [COL_A] IS NULL then (1) else (0) end
+case when [COL_B] IS NULL then (1) else (0) end)
+case when [COL_C] IS NULL then (1) else (0) end/(3.0)
) PERSISTED
) ON [PRIMARY]