質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.12%

mysql縦持ちのデータを横持ちに入れ替える方法*追記ありlaravel csv出力方法

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 685

sql

score 12

前提・実現したいこと

現在のデータベース

id user_id name
1 1 サッカー
2 1 野球
3 1 陸上
4 2 野球
5 2 水泳
6 3 テニス
7 4 野球
8 4 陸上

まとめたいデータベース

user_id name1 name2 name3
1 サッカー 野球 陸上
2 野球 水泳
3 テニス
4 野球 陸上

発生している問題・エラーメッセージ

[42000][1064] You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right 
syntax to use near '(partition by user_id) as seq from sample_table ) 
tmp group ...

https://dev.classmethod.jp/etc/sql-data-horizontal-vertical/
上記のURLより横にデータを変更する方法を見つけました。

しかし、 ,row_number() over (partition by employee_id) as seqでsyntaxが出ました。
それと上記のURLのものでは横のカラムが固定のもの(qualification_id1~4)になってしまうためそのままでは使用できませんでした。

自分のものではnameのカラムは動的にしたいです。
ユーザーが持っているnameの数だけname(n)のように増やしたいです。

該当のソースコード

select
  tmp.user_id,
  max(case tmp.seq
      when 1
        then tmp.name
      else null end) as name1,
  max(case tmp.seq
      when 2
        then tmp.name
      else null end) as name2,
  max(case tmp.seq
      when 3
        then tmp.name
      else null end) as name3,
  max(case tmp.seq
      when 4
        then tmp.name
      else null end) as name4
from
  (
    select
      user_id,
      name,
      row_number() over (partition by user_id) as seq
    from
      sample_table
  ) tmp
group by
  tmp.user_id;

放り投げの質問になってしまって申し訳ありませんが、ご教授、ご対応できる方がいましたら急ぎではありませんのでご対応していただけるとありがたいです。よろしくお願いいたします。

追記(2019/05/04)

userテーブル

id age user_name zip address
1 10 斎藤 111-1111 東京都サンプル区サンプル1-1-1
2 11 近藤 111-1111 東京都サンプル区サンプル1-1-1
3 12 大久保 111-1111 東京都サンプル区サンプル1-1-1
4 23 中田 111-1111 東京都サンプル区サンプル1-1-1

sampleテーブル

id user_id name
1 1 サッカー
2 1 野球
3 1 陸上
4 2 野球
5 2 水泳
6 3 テニス
7 4 野球
8 4 陸上

csvでの出力

id age user_name zip address name1 name2 name3
1 10 斎藤 111-1111 東京都サンプル区サンプル1-1-1 サッカー 野球 陸上
2 11 近藤 111-1111 東京都サンプル区サンプル1-1-1 野球 水泳
3 12 大久保 111-1111 東京都サンプル区サンプル1-1-1 テニス
4 23 中田 111-1111 東京都サンプル区サンプル1-1-1 野球 陸上

laravelで上記のようにcsvを出力させたいです。ご教授お願いいたします。

        //ヘッダーを作成
        $headers = ['id', 'age', 'user_name', 'zip', 'address'];
        foreach ($headers as $header) {
            $arr[0][] = $header;
        }

        //BODYを作成
        $items = User::select('*')->get();
        foreach ($items as $key => $item) {
            $arr[$key + 1] = $item;
        }

        $fp = fopen('file.csv', 'w');

        foreach ($arr as $fields) {
            fputcsv($fp, $fields);
        }

        fclose($fp);

上記で出力されるcsv

id age user_name zip address
1 10 斎藤 111-1111 東京都サンプル区サンプル1-1-1
2 11 近藤 111-1111 東京都サンプル区サンプル1-1-1
3 12 大久保 111-1111 東京都サンプル区サンプル1-1-1
4 23 中田 111-1111 東京都サンプル区サンプル1-1-1
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

カラム数が可変だと、SQLだけでは無理です。
ストアドプロシージャで動的なSQLを発行するか、クライアント側で処理するなど別の手段が必要です。
SQLはそもそも視覚情報化には不向きですから、後者をお勧めします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/04 17:22

    返答ありがとうございます。
    アドバイスの方法も検討させていただきたいと思います。
    追記情報も記述しましたので可能であれば対応方法がありましたらご教授いただけるとありがたいです。

    キャンセル

  • 2019/05/06 17:54

    もし可変長カラムのCSVを考えているとしたら、地雷極まりないので考え直してください。
    CSVにするなら、せっかくuserテーブルとsampleテーブルに分かれているのですから、そのまま2つ渡すのがベターです。
    より良くしたいならJSONなどデータ構造を持たせられる形式を使うといいでしょう。

    キャンセル

0

GROUP_CONCATを試しては?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/04 17:23

    返答ありがとうございます。
    アドバイスの方法も検討させていただきたいと思います。
    追記情報も記述しましたので可能であれば対応方法がありましたらご教授いただけるとありがたいです。

    キャンセル

0

laravel-excel を使うと比較的楽に実装できると思います。
https://laravel-excel.com/

参考
https://www.ritolab.com/entry/160#aj_8

補足

  • row_number() over はMySQLでは利用できないので、Blade側で加工するのが良いと思います。 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/05 08:24

    アドバイスありがとうございます。
    参考にさせていただきます。

    csvでの出力の表のようにbladeで加工する良い方法ソースをいただけるとありがたいですがご教授いtだけませんでしょうか?

    キャンセル

  • 2019/05/05 10:42

    それは作業依頼ですね。
    まずは、ご自身でやってみて、より具体的な問題が解決できない場合に再度質問してください。

    キャンセル

0

sampleテーブルのデータのもたせ方次第ですね
もしsampleテーブルでnameの何列目かまでデータを保持できるならできます

id user_id col name
1 1 1 サッカー
2 1 2 野球
3 1 3 陸上
4 2 1 野球
5 2 2 水泳
6 3 1 テニス
7 4 1 野球
8 4 2 陸上

そうでない場合はいくつデータを横に伸ばせばいいのかSQLでは判断つかないので
普通にはできません。
(group_concatならできますが、その場合csvに出力時にやや不都合がありそうです)

どうしてもいまのデータのままでやりたいならプロシージャを組むしかないでしょう

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる