5

假设我有一个具有如下水平结构的数据库:

ID | NAME | DATA1 | DATA2 | DATA3 | DATA4 | DATA5 | DATA6 | DATA7
 1 |  mmm |   0   |   1   |   0   |   3   |   5   |   1   |   0
 2 |  bbb |   0   |   0   |   0   |   1   |   0   |   1   |   1

信息是数据字段,我想计算某个判别式的所有时间,例如“大于 0”

我认为它是循环遍历所有字段,计数或COUNT()每个DATA字段的方式,所以SUM()这些7查询......有人有另一个想法吗?

在这种情况下,结果"count every DATA field with a value over 0"是 = 7

4

2 回答 2

5

没有内置语法允许您动态引用一组列,即无需显式命名它们。如果您想要动态性,则需要查询元数据以获取所需的列名,然后动态构建最终查询。

但在此之前,您仍然需要了解动态查询应该如何执行工作本身。因此,您首先需要解决有限列集上的问题。

解决这个问题的方法不止一种。@bluefeet 建议的方法可能是更清晰但效率较低的方法之一。您可以尝试至少两种选择:

  1. 使用条件聚合分别计算每一列,并将所有结果加到一个表达式中:

    SELECT
      COUNT(DATA1 > 0 OR NULL) +
      COUNT(DATA2 > 0 OR NULL) +
      COUNT(DATA3 > 0 OR NULL) +
      COUNT(DATA4 > 0 OR NULL) +
      COUNT(DATA5 > 0 OR NULL) +
      COUNT(DATA6 > 0 OR NULL) +
      COUNT(DATA7 > 0 OR NULL) AS TOTAL
    FROM yourtable
    ;
    

    OR NULL技巧在这里解释。)

  2. 使用交叉连接将列取消透视DATA到虚拟表,然后将条件应用于未透视列:

    SELECT
      COUNT(*) AS TOTAL
    FROM (
      SELECT
        CASE s.col
          WHEN 'DATA1' THEN DATA1
          WHEN 'DATA2' THEN DATA2
          WHEN 'DATA3' THEN DATA3
          WHEN 'DATA4' THEN DATA4
          WHEN 'DATA5' THEN DATA5
          WHEN 'DATA6' THEN DATA6
          WHEN 'DATA7' THEN DATA7
        END AS DATA
      FROM yourtable
      CROSS JOIN (
        SELECT 'DATA1' AS col
        UNION ALL SELECT 'DATA2'
        UNION ALL SELECT 'DATA3'
        UNION ALL SELECT 'DATA4'
        UNION ALL SELECT 'DATA5'
        UNION ALL SELECT 'DATA6'
        UNION ALL SELECT 'DATA7'
      ) s
    ) s
    WHERE DATA > 0
    ;
    

    (在某种程度上,这类似于@bluefeet 的建议,只是不使用任何 UNION。)

于 2013-02-27T08:56:46.740 回答
3

由于您的数据未标准化,因此您应该取消数据透视以获得结果。MySQL 没有 unpivot 函数,因此您可以使用UNION ALL查询将列转换为行。一旦数据在行中,您就可以轻松计算值的数量。我会使用类似的东西:

select count(*) total
from
(
  select id, name, 'data1' col, data1 as value
  from yourtable
  union all
  select id, name, 'data2' col, data2 as value
  from yourtable
  union all
  select id, name, 'data3' col, data3 as value
  from yourtable
  union all
  select id, name, 'data4' col, data4 as value
  from yourtable
  union all
  select id, name, 'data5' col, data5 as value
  from yourtable
  union all
  select id, name, 'data6' col, data6 as value
  from yourtable
  union all
  select id, name, 'data7' col, data7 as value
  from yourtable
) src
where value > 0

请参阅带有演示的 SQL Fiddle

于 2013-02-26T13:57:41.183 回答