culage
@culage

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

複数テーブルから全項目を取得するときに、テーブル名と列名を分かるように取得するには?

Q&A

Closed

質問

MySQL8にて、SELECT文で複数テーブルを結合して全ての列を取得したいと考えています。
複数テーブルを結合して全ての列を取得するとき、重複する列名があると自動的に重複しない項目名がつきますが、この自動的につく項目名ではどのテーブルの列なのか判別できません。

各テーブルの各列をSELECT句に列挙してASで適切な項目名をつければどのテーブルの列なのか判別できますが、テーブル定義が変わったときに追従してSQLを変更しなくても済むようにしたいです。
テーブル名と列名が分かる項目名で、自動的に全列を取得する方法はないでしょうか?

SELECT例

select *
  from 売上データ
  left join 商品マスタ on 売上データ.商品コード = 商品マスタ.商品コード

理想とする取得結果(実際にはこうならない)

売上データ.売上ID 売上データ.商品コード 売上データ.売上個数 売上データ.更新ユーザ 商品マスタ.商品コード 商品マスタ.商品名 商品マスタ.更新ユーザ
1 item01 10 user01 item01 りんご user99
2 item02 20 user01 item02 みかん user99
3 item03 30 user01 item03 バナナ user99

実際の取得結果

売上ID 商品コード 売上個数 更新ユーザ 商品コード_1 商品名 更新ユーザ_1
1 item01 10 user01 item01 りんご user99
2 item02 20 user01 item02 みかん user99
3 item03 30 user01 item03 バナナ user99
0

2Answer

私も同様の問題に遭遇したとき、綺麗かどうかは別にして、動的クエリで何とかしました。
こういう感じです。

SET group_concat_max_len = 65535; /* concatの結果が切れないようにする */

SET @tbl1 = 'table_1';
SET @cols1 = 
  (
    SELECT
      GROUP_CONCAT(CONCAT('`', @tbl1 ,'`.`',COLUMN_NAME,'` as \'', @tbl1 , '.', COLUMN_NAME, '\'') SEPARATOR ', \n')
    FROM
      INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = database()
      AND TABLE_NAME = @tbl1
  );  

SET @tbl2 = 'table_2';
SET @cols2 = 
  (
    SELECT
      GROUP_CONCAT(CONCAT('`', @tbl2 ,'`.`',COLUMN_NAME,'` as \'', @tbl2 , '.', COLUMN_NAME, '\'') SEPARATOR ', \n')
    FROM
      INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = database()
      AND TABLE_NAME = @tbl2
  );  
 
SET @query = concat(
'select\n', 
@cols1,',\n',
@cols2,'\n',
'FROM\n', 
'table_1\n',
'left join table_2 on table_1.id = table_2.table_1_id 
');

PREPARE select_data FROM @query;
EXECUTE select_data;
DEALLOCATE PREPARE select_data;

1Like

Comments

  1. @culage

    Questioner

    ありがとうございます。
    GROUP_CONCATで自動的かつ効率的に項目名のリストが作成できますね。素晴らしいです。

MySQL 8では、SELECT *を使用して複数のテーブルを結合した場合、自動的に全ての列を取得する際にテーブル名と列名を含む項目名を生成する機能は提供されていません。重複する列名がある場合、SQL自体は重複する列名を区別するために自動的に別名を付けることはありますが(例: 商品コード商品コード_1)、これはテーブル名を含む明確な区別ではありません。

解決策:

  1. 手動で列を指定: SQLクエリで各列を手動で指定し、ASを使用して明示的に列名を設定する方法があります。このアプローチは、質問で述べたように、テーブル定義が変更された場合にSQLを更新する必要があります。

: 手動で列を指定してエイリアスを設定する方法の例

SELECT
    売上データ.売上ID AS `売上データ.売上ID`,
    売上データ.商品コード AS `売上データ.商品コード`,
    売上データ.売上個数 AS `売上データ.売上個数`,
    売上データ.更新ユーザ AS `売上データ.更新ユーザ`,
    商品マスタ.商品コード AS `商品マスタ.商品コード`,
    商品マスタ.商品名 AS `商品マスタ.商品名`,
    商品マスタ.更新ユーザ AS `商品マスタ.更新ユーザ`
FROM 売上データ
LEFT JOIN 商品マスタ ON 売上データ.商品コード = 商品マスタ.商品コード;

このアプローチでは、各列に対して明示的にエイリアスを設定しています。しかし、テーブルに新しい列が追加された場合や列名が変更された場合には、このSQLを更新する必要があります。

0Like

Comments

  1. @culage

    Questioner

    回答ありがとうございます。
    しかしこの回答は質問文で示される「テーブル定義が変わったときに追従してSQLを変更しなくても済むようにしたい」という要件を満たしません。

Your answer might help someone💌