0

基本的に、日時列とカテゴリ列を含む mysql db テーブルがあります。カテゴリ列に存在するすべての値を取得し、datetime 列の月/年でグループ化された各カテゴリ値の出現回数をカウントする SQL クエリを作成したいと考えています。できれば合計も返してほしいです。1 か月のすべての発生回数の合計と、カウントされたカテゴリの合計。

注:カテゴリ値はユーザーによって設定され、別のテーブルに格納されるため、ハードコーディングできません。

DB テーブルには次の構造があります。

datetime    |  category

2009-01-05  |  fish
2009-01-06  |  fish
2009-01-06  |  potato
2009-01-16  |  fish
2009-02-08  |  pineapple
2009-02-15  |  potato

クエリから返された結果は次のようになります。

Month    |  fish  |  potato  |  pineapple   |  total

2009-01  |   3    |   1      |   0          |    4
2009-02  |   0    |   1      |   1          |    2

Total    |   3    |   2      |   1          |    6

単一の SQL クエリで実行できると思います (希望) が、方法がわかりません。誰でも私を助けることができますか?

ありがとう!

4

2 に答える 2

2

まず、これはプレゼンテーション ロジック (php コード) で処理する問題のように感じられると思います。ただし、SQL はそのような結果を生成する可能性があります。あなたは2つの異なることを達成しようとしています。

まず、テーブルを探していPIVOTます。MySQL はこのコマンドをサポートしていませんが、とPIVOTでシミュレートできます。これは、潜在的なカテゴリの数がわかっている場合はうまく機能しますが、あなたの場合は機能しません。MAXCASE

次に、行の合計を取得し、次に最終的な合計行を取得します。 繰り返しますが、これはプレゼンテーション層で処理する方が適切です。

ただし、 を使用すると、表と行Dynamic SQLの両方のPIVOT合計を取得できます。サンプルコードは次のとおりです。

まず、PIVOT 変数 @sql を作成します。

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'COUNT(IF(category = ''', category, ''',1,NULL)) AS ', category)
  ) INTO @sql
FROM (
    SELECT *, 
      @rn:=IF(@prevMonthYear=CONCAT(YEAR(datetime),'-',MONTH(datetime)),@rn+1,1) rn,
      @prevMonthYear:=CONCAT(YEAR(datetime),'-',MONTH(datetime)) dt
    FROM yourtable JOIN (SELECT @rn:=0,@prevParent:=0) t
) t
;

次に、Row Summary 変数 @totsql を作成します。

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'SUM(', category, ') AS sum_', category)
  ) INTO @totsql
FROM (
    SELECT *, 
      @rn:=IF(@prevMonthYear=CONCAT(YEAR(datetime),'-',MONTH(datetime)),@rn+1,1) rn,
      @prevMonthYear:=CONCAT(YEAR(datetime),'-',MONTH(datetime)) dt
    FROM yourtable JOIN (SELECT @rn:=0,@prevParent:=0) t
) t
;

すべてをまとめる:

SET @sql = CONCAT('SELECT dt,
                          ', @sql, ', COUNT(1) total
                  FROM (
                  SELECT *, 
                        @rn:=IF(@prevMonthYear=CONCAT(YEAR(datetime),''-'',MONTH(datetime)),@rn+1,1) rn,
                        @prevMonthYear:=CONCAT(YEAR(datetime),''-'',MONTH(datetime)) dt
                      FROM yourtable JOIN (SELECT @rn:=0,@prevParent:=0) t
                  ) t
                  GROUP BY dt

                  UNION 
                  SELECT ''Totals'',', @totsql, ', SUM(total)  
                  FROM (

                    SELECT dt,
                            ', @sql, ', COUNT(1) total
                    FROM (
                    SELECT *, 
                          @rn:=IF(@prevMonthYear=CONCAT(YEAR(datetime),''-'',MONTH(datetime)),@rn+1,1) rn,
                          @prevMonthYear:=CONCAT(YEAR(datetime),''-'',MONTH(datetime)) dt
                        FROM yourtable JOIN (SELECT @rn:=0,@prevParent:=0) t
                    ) t
                    GROUP BY dt

                  ) t2
                  ;');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

結果:

MONTH       FISH   POTATO   PINEAPPLE   TOTAL
2009-1      3      1        0           4
2009-2      0      1        1           2
Totals      3      2        1           6
于 2013-05-31T02:57:17.393 に答える
0

この場合、複数のネストされたクエリを使用するか、mysql ループを使用できます。最も簡単なのは、必要なすべてのデータを取得し、php を使用して処理することです。

于 2013-05-31T03:18:08.107 に答える