【问题标题】:Count number of table columns that are not null - MS Access SQL计算不为空的表列数 - MS Access SQL
【发布时间】:2019-07-02 07:42:10
【问题描述】:

我有一个表格,我在下面展示了一个简化示例:

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

但实际上我使用的真实表有一百多列,我宁愿避免写出每列的名称。有没有更简单的方法来做到这一点?

【问题讨论】:

    标签: sql ms-access


    【解决方案1】:

    您可以使用 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 - 但我知道这并不总是可行的。

    【讨论】:

    • 谢谢唐乔治。是的,我刚决定走这条路。感谢您将这段代码放在一起。我曾希望仅使用 SQL 就可以做到这一点,但最重要的是找到一个可行的解决方案,就像这样
    【解决方案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
    

    【讨论】:

    • 我同意数据应该垂直存储。我继承了当前状态的数据库,很可能需要彻底检查表的结构方式。我处于需要在某个截止日期之前进行更新的位置,并希望在那之前找到更快的解决方法。我想知道是否有一种有效的方法可以使用 SQL 来执行此操作,但现在已经走上了使用 VBA 循环遍历记录集中的字段并以这种方式递增计数器的路线。
    【解决方案3】:

    你可以减少一点:

    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
    

    【讨论】:

    • 谢谢 Gustav,我没想到,这有点好。我现在决定使用 VBA 来实现这一点,但我仍然有兴趣看看它是否可以用纯 SQL 来完成,如果只是出于好奇
    猜你喜欢
    • 1970-01-01
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    相关资源
    最近更新 更多