web-dev-qa-db-ja.com

列値をSQLクエリ結果の列名として設定する

SQLクエリ結果の列名になる値を持つテーブルを読みたかった。たとえば、私はtable1を..として使用しています。

id    col1     col2
----------------------
0      name    ax
0      name2   bx
0      name3   cx
1      name    dx
1      name2   ex
1      name3   fx                

Id = 0の場合、nameの値はaxで、name2はbx、name3はcxです。これを行にする代わりに、列をid、name、name2、name3として表示する方が簡単です。クエリの結果を次のようにしたいと思います。

id   name    name2     name3
0    ax      bx         cx
1    dx      ex         fx

誰かがこれを達成するのを助けてくれますか?

13
ravi

これは、ピボットテーブルで行われます。 idでグループ化して、列にキャプチャする値ごとにCASEステートメントを発行し、MAX()集計などを使用してnullを削除し、1つに折りたたみます行。

SELECT
  id,
  /* if col1 matches the name string of this CASE, return col2, otherwise return NULL */
  /* Then, the outer MAX() aggregate will eliminate all NULLs and collapse it down to one row per id */
  MAX(CASE WHEN (col1 = 'name') THEN col2 ELSE NULL END) AS name,
  MAX(CASE WHEN (col1 = 'name2') THEN col2 ELSE NULL END) AS name2,
  MAX(CASE WHEN (col1 = 'name3') THEN col2 ELSE NULL END) AS name3
FROM
  yourtable
GROUP BY id
ORDER BY id

これは実際のサンプルです

注:これは、col1の可能な既知の数の有限値に対してのみ機能します。可能な値の数が不明な場合は、SQLステートメントをループで動的に作成する必要があります。

18

あなたがしようとしているのはPIVOTです。MySQLにはPIVOT関数がないので、CASEと集約関数を使用してこれを複製できます。

列の数がわかっている場合は、静的バージョンを使用して値をハードコードできます。これに似ています( SQL Fiddleデモあり を参照):

select id,
  max(case when col1='name' then col2 end) name,
  max(case when col1='name2' then col2 end) name2,
  max(case when col1='name3' then col2 end) name3
from yourtable
group by id

しかし、列の数が不明な場合は、準備済みステートメントを使用してこれを動的に作成できます。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when col1 = ''',
      col1,
      ''' then col2 end) AS ',
      col1
    )
  ) INTO @sql
FROM yourtable;

SET @sql = CONCAT('SELECT id, ', @sql, ' 
                  FROM yourtable 
                  GROUP BY id');

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

参照 SQL Fiddleデモあり

7
Taryn
select id,
    max(if(tablename.columnname = 'name',tablename.columnname,null)) as namealise,
    max(if(tablename.columnname = 'name1',tablename.columnname,null)) as namealise1 
from table1, table2 
where table1.id = table2.id 
group by table1.id 
order by table1.id
0