我有一张桌子,我在下面展示了一个简化的例子:
ID | Item1 | Item2 | Item3 | Item4 | Item5
------------------------------------------
A | NULL | NULL | YES | YES | NULL
B | NULL | NULL | NULL | YES | NULL
C | NULL | NULL | NULL | NULL | NULL
我想返回以下数据集:
ID | Count
------------
A | 2
B | 1
C | 0
即。我想要计算该ID
中有多少列不是NULL
一个可能的解决方案是
SELECT
ID,
SUM(
IIf(Item1 is NULL,0,1)
+
IIf(Item2 is NULL,0,1)
+
IIf(Item3 is NULL,0,1)
+
IIf(Item4 is NULL,0,1)
+
IIf(Item5 is NULL,0,1)
) 'Count'
FROM
tableName
GROUP BY
ID
然而在实践中,我使用的真实表有超过一百列,我宁愿避免写出每列的名称。有更简单的方法吗?
答案 0 :(得分:2)
您的数据未正常化,因此您必须在代码中执行体操才能解决问题。
您的数据应垂直存储而不是水平存储;
ID | ItemNo | Value
---------------------
A | 2 | 1
A | 3 | 1
B | 4 | 1
这会使您的查询成为一个简单的总查询,并允许任意数量的项目。当你有一些不是每种情况时,你也只存储数据。
编辑:这将遍历字段
Dim Rst As Recordset
Dim f As Field
Set Rst = CurrentDb.OpenRecordset(TableName)
For Each f In Rst.Fields
Debug.Print (f.name)
Next
Rst.Close
答案 1 :(得分:2)
您可以使用VBA循环遍历每个记录和字段:
Function CountFields()
Set db = CurrentDb()
db.Execute ("delete * from ItemCounts")
Set RS = db.OpenRecordset("select * from [DataTable]")
RS.MoveFirst
Do While Not RS.EOF
Id = RS.Fields("ID").Value
Count = 0
For Each Item In RS.Fields
If (Item.Name <> "ID" And RS.Fields(Item.Name).Value <> "") Then Count = Count + 1
Next Item
db.Execute ("insert into ItemCounts (ID,[count]) select " & Id & "," & Count)
RS.MoveNext
Loop
MsgBox ("done")
End Function
这将计数放在名为ItemCounts的表中,需要在执行VBA之前设置。该表中的字段是ID和Count。
而且,如果您可以重新格式化源数据,我同意Minty - 但我知道并不总是可行。
答案 2 :(得分:1)
你可以减少一点:
SELECT
ID,
ABS(SUM((Item1 is Not NULL)+(Item2 is Not NULL)+(Item3 is Not NULL)+(Item4 is Not NULL)+(Item5 is Not NULL))) As [Count]
FROM
tableName
GROUP BY
ID
答案 3 :(得分:-1)
顺便说一句,这里是水平而不是垂直执行查询的地方,这是很多年来包括我自己在内的许多人所遇到的问题。
OP的示例数据显示为YES或为null,但未描述表的数据结构,它们可以是布尔值/复选框,在这种情况下查询非常容易,并且OP并没有明确要求。但是,这仍然是一个基本问题,有时其他答案也会与此吻合,但我尚未找到一个答案。取而代之的是,人们对“您为什么要这样做?”表示反对。并没有真正深入问题的底部。
yes / NO / Null布尔值(-1或0)是一个简单的查询,然后在查询中添加一列
计数:[Field1] + [Field2] + [Field3] + [Field4] + [Field5]是可更新的查询。
也许有人链接到评估不为空的计数,这会有所帮助