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つです。少なくとも2つの選択肢を試すことができます。

  1. 条件付き集計を使用してすべての列を個別にカウントし、すべての結果を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 FiddlewithDemoを参照してください

于 2013-02-26T13:57:41.183 に答える