web-dev-qa-db-ja.com

列の自動列挙を使用してMySQLでテーブルを作成する方法は?

例。私のデータはテーブル名:BIKEからのものです

Bike_No   Repair_Date     Repair_Cost
--------  -----------     ------------
ABC1234   2013-01-05      50.00
BMX5678   2013-02-04      75.00
ABC1234   2013-01-25      20.00
BON3333   2013-03-06      80.00
DEB1111   2013-08-04      40.00
ABC1234   2013-09-06      50.00

日付範囲(例:2013年1月1日から2013年3月31日まで)に基づいて各自転車の修理費を確認したいのですが、結果テーブルには、Bike_Noと影響を受ける月を列として修理費を表示する必要があります。クエリされた日付範囲に基づいて、影響を受ける月を列としてどのように生成しますか?

3
John Seagull

残念ながら、MySQLにはPIVOT関数がないため、データを次の形式に変換しようとしているようです。

+---------+-----------------+-----------------+-----------------+
| bike_no | repair_cost_Jan | repair_cost_Feb | repair_cost_Mar |
+---------+-----------------+-----------------+-----------------+
| ABC1234 |              70 |               0 |               0 |
| BMX5678 |               0 |              75 |               0 |
| BON3333 |               0 |               0 |              80 |
+---------+-----------------+-----------------+-----------------+

その場合、MySQLでは、CASE式とともに集計関数を使用して、データの行を列に変換する必要があります。

返される月数がわかっている場合は、次のようなクエリを簡単にハードコードできます。

select bike_no,
  sum(case when month(repair_date) = 1 then repair_cost else 0 end) repair_cost_Jan,
  sum(case when month(repair_date) = 2 then repair_cost else 0 end) repair_cost_Feb,
  sum(case when month(repair_date) = 3 then repair_cost else 0 end) repair_cost_Mar
from bike
where repair_date >= '2013-01-01'
  and repair_date <= '2013-03-31'
group by bike_no;

SQL Fiddle with Demo を参照してください。

しかし、あなたの場合、開始日と終了日をクエリに変更したいようです。その場合は、実行される 動的SQLを生成するために準備されたステートメント を使用する必要があります。

SET @sql = NULL;
set @startdate = '2013-01-01';
set @enddate = '2013-03-31';
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN month(repair_date) = ',
      month(repair_date),
      ' THEN repair_cost else 0 END) AS `repair_cost_',
      monthname(repair_date), '`'
    )
  ) INTO @sql
FROM bike
where repair_date >= @startdate
 and repair_date <= @enddate;

SET @sql 
  = CONCAT('SELECT bike_no, ', @sql, ' 
            from bike
            where repair_date >= ''',  @startdate, ''' 
               and repair_date <= ''', @enddate, ''' 
            group by bike_no');

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

SQL Fiddle with Demo を参照してください。どちらのクエリでも上記のデータのテーブルが生成されます。

4
Taryn