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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CodeIgniter

CodeIgniterは、PHP向けオープンソースのWebアプリケーションフレームワークです。CodeIgniterは覚える構文が少なく、自由度も高いため、PHPを理解していれば構築が簡単です。

Q&A

解決済

2回答

3495閲覧

mysqlから取得した配列を整形したい

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CodeIgniter

CodeIgniterは、PHP向けオープンソースのWebアプリケーションフレームワークです。CodeIgniterは覚える構文が少なく、自由度も高いため、PHPを理解していれば構築が簡単です。

0グッド

0クリップ

投稿2016/11/08 07:16

編集2016/11/10 02:36

DBからレコードを取得した値が、以下のような形で配列に格納されています。

php

1array(14) { 2 [0]=> 3 array(7) { 4 ["office_id"]=> 5 string(4) "0000" 6 ["area_id"]=> 7 string(4) "0000" 8 ["c_id"]=> 9 string(7) "0000000" 10 ["date"]=> 11 string(10) "2016-10-25" 12 ["sum_num"]=> 13 string(1) "6" 14 } 15 [1]=> 16 array(7) { 17 ["office_id"]=> 18 string(4) "0000" 19 ["area_id"]=> 20 string(4) "0000" 21 ["c_id"]=> 22 string(7) "0000000" 23 ["date"]=> 24 string(10) "2016-10-26" 25 ["sum_num"]=> 26 string(1) "2" 27 } 28 [2]=> 29 array(7) { 30 ["office_id"]=> 31 string(4) "0000" 32 ["area_id"]=> 33 string(4) "0000" 34 ["c_id"]=> 35 string(7) "0000000" 36 ["date"]=> 37 string(10) "2016-11-01" 38 ["sum_num"]=> 39 string(1) "4" 40 } 41 [3]=> 42 array(7) { 43 ["office_id"]=> 44 string(4) "0000" 45 ["area_id"]=> 46 string(4) "0000" 47 ["c_id"]=> 48 string(7) "0000000" 49 ["date"]=> 50 string(10) "2016-11-04" 51 ["sum_num"]=> 52 string(1) "2" 53 } 54 [4]=> 55 array(7) { 56 ["office_id"]=> 57 string(4) "0000" 58 ["area_id"]=> 59 string(4) "0000" 60 ["c_id"]=> 61 string(7) "0000000" 62 ["date"]=> 63 string(10) "2016-11-07" 64 ["sum_num"]=> 65 string(1) "1" 66 } 67 [5]=> 68 array(7) { 69 ["office_id"]=> 70 string(4) "0000" 71 ["area_id"]=> 72 string(4) "0000" 73 ["c_id"]=> 74 string(7) "0000003" 75 ["date"]=> 76 string(10) "2016-11-01" 77 ["sum_num"]=> 78 string(1) "2" 79 } 80 81828384} 85

view側ではforeachで回し

office_idarea_idc_iddatesum_num
0000000000000002016-10-256
0000000000000002016-10-262
0000000000000002016-11-014
...

このように表示しています。

これを同じc_idはまとめて、日付のみ後ろに付け足していきたいです。

office_idarea_idc_iddatesum_numdatesum_numdatesum_num
0000000000000002016-10-2562016-10-2622016-11-014
...

さらにレコードがない日付は空白が入るようにしたいです。
|office_id|area_id|c_id|date|sum_num|date|sum_num|date|sum_num|
|---|---|---|---|---|
|0000|0000|0000000|2016-10-25|6|2016-10-26|2|2016-11-01|4|
|0000|0000|0000001|2016-10-25|6|2016-10-26|2|||
|0000|0000|0000002|||2016-10-26|2|2016-11-01|4|
|...|||||||||

よろしくお願いします。

**追記
c_idが同じレコードはoffice_id,area_idは等しいです。
ただし、c_idが違ってもoffice_id,area_idが同じ場合はあります。
レコードのMAXは可変です。一番多いレコード数分横並びにします。

また最終的には

office_idarea_idc_id2016-10-252016-10-262016-11-012016-11-04
000000000000000624
00000000000000162
00000000000000224
...

このような形で出力したいと考えております。
**

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiim

2016/11/08 07:23

c_idが同じレコードはoffice_idもarea_idも等しいと保証されてますか?また上記のまとめ方はc_idにまとめた時、最大で3レコード分になってますが、MAX3レコード固定ですか?それとも可変(一番多かったレコード数分横並びにさせるという事ですか?)
退会済みユーザー

退会済みユーザー

2016/11/08 07:36

情報が少なく失礼いたしました。
guest

回答2

0

効率的かどうかはともかく、せっかくなのでプロシージャでやる方法を提示しておきます。
テーブルの形式が明確ではないのでちょっと簡略化して表示します

SQL

1create table tbl(a int,b int,c int,d date,e int); 2insert into tbl values(0,0,0,'2016-10-25',6),(0,0,0,'2016-10-26',2),(0,0,0,'2016-11-01',4),(0,0,1,'2016-10-25',6),(0,0,1,'2016-10-26',2),(0,0,2,'2016-10-26',2),(0,0,2,'2016-11-01',4)

以下プロシージャを作ります

sql

1drop procedure if exists view; 2delimiter // 3create procedure view() 4begin 5declare x1,x2,x3,x5 int; 6declare x4 date; 7declare done int default 0; 8declare cur cursor for 9select a,b,c,d,e from tbl; 10declare continue handler for sqlstate '02000' set done = 1; 11set @a:=(select concat('`',group_concat(distinct d order by d asc separator '` int null,`'),'` int null') from tbl); 12set @sql=concat('create temporary table tmp_tbl(`a` int,`b` int,`c` int,',@a,',unique(`a`,`b`,`c`))'); 13prepare stmt from @sql; 14execute stmt; 15open cur; 16repeat 17fetch cur into x1,x2,x3,x4,x5; 18set @sql=concat('insert into tmp_tbl(a,b,c,`',x4,'`) values("',x1,'","',x2,'","',x3,'","',x5,'") '); 19set @sql=concat(@sql,'on duplicate key update `',x4,'`=',x5); 20prepare stmt from @sql; 21execute stmt; 22until done end repeat; 23close cur; 24select * from tmp_tbl; 25end 26// 27delimiter ;

プロシージャを実行します
データの追加削除をした後以下を実行すればその時々の状況が確認できます

SQL

1call view();

投稿2016/11/08 11:51

編集2016/11/08 11:59
yambejp

総合スコア114777

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/11/10 02:42

御回答ありがとうございます。 プロシージャというものを、そもそも知らなくて大変勉強になりました。 まだ試せておりませんが、ご参考にさせていただきます。
guest

0

ベストアンサー

DBから質問にあるような形式で取得してからの処理であれば、スマートなコード書けずかなり冗長な気もしますが
DBから取得した配列を$dbrecordsとして

php

1$output = array(); 2foreach($dbrecords as $record) 3{ 4 if(!isset($output[$record["c_id"]])) 5 $output[$record["c_id"]] = array( 6 'office_id' =>$record['office_id'], 7 'area_id'=>$record['area_id'], 8 'items'=>array() 9 ); 10 11 $output[$record["c_id"]]['items'][] = array( 12 'date'=>$record['date'], 13 'sum_num'=>$record['sum_num'] 14 ); 15}

view側で

php

1foreach($output as $c_id=>$items) 2{ 3 printf("<tr><td>%s</td><td>%s</td><td>%s</td>",$c_id,$items['office_id'],$items['area_id']); 4 5 foreach($items['items'] as $key=>$item) 6 { 7 printf("<td>%s</td><td>%s</td>",$item['date'],$item['sum_num']); 8 } 9 10 // ここで最大数に満たないレコードのtd埋めするなどの処理 11 12 13 echo('</tr>'); 14}

DBからmaxとcountを使って先に最大何列になるか取得しておくとtdで埋めるの楽かな?と思います。
あまりスマートな方法ではないですが、、、

投稿2016/11/08 08:12

hiim

総合スコア1689

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/11/10 02:31 編集

ご回答ありがとうございました。 上記の方法で、配列に同じc_idをまとめて格納することができました。 |office_id|area_id|c_id|date|sum_num|date|sum_num|date|sum_num| |---|---|---|---|---|---|---|---|---| |0000|0000|0000000|2016-10-25|6|2016-10-26|2|2016-11-01|4| |0000|0000|0000001|2016-10-25|6|2016-10-26|2||| |0000|0000|0000002|||2016-10-26|2|2016-11-01|4| |...||||||||| ただ上記の表の様に表示するためには、レコードのない日付の部分を同じ列で揃える方法が上手くいきませんでした。 全ての日付を一度取得し、その日付があるか調べるといった方法を考えましたが、上手く実装できませんでした。 また最終的には |office_id|area_id|c_id|2016-10-25|2016-10-26|2016-11-01|2016-11-04| |---|---|---|---|---|---|---| |0000|0000|0000000|6|2|4| |0000|0000|0000001|6|2||| |0000|0000|0000002|||2|4| |...||||||||| といったように日付は一番上の<th>で一回のみ出力ということを考えております。 上に書いた日付を一度取得し、という方法ではなく 表の<th>にあたる部分とそれ以外は別の配列にそれぞれ格納するといった方法を考えたほうが良いのでしょうか?
hiim

2016/11/10 02:40

まず根本的なところになりますが、今回の回答はDBからデータを取り出した値を整形するという方法をとりましたが、DBからデータを取得する段階から変更可能であればその段階でより最終のデータに近い形でデータを取得する方法はいろいろあると思うのですがどうですか?
退会済みユーザー

退会済みユーザー

2016/11/10 02:46

御回答ありがとうございます。 そうですね。レコード取得時点で、最終データに近い形で取得できるべきならそうするべきですね。 自分の知識では、この形で取得することが限界だと考えており、そこから整形でどうにかするしかないと考えていました。 もう少し、レコードの取得方法について勉強してみます。
hiim

2016/11/10 02:50

基本的な考えとしては最終のフォーマットに近いデータをSQLで取得し、それで補いきれない箇所をphp側の処理でするのが理想ですね。もっと厳密にいうならSQL側にさせた方が早い(負荷が低い)のかphp側でさせたほうが早いのかのトレードオフで、、、DB構造はよくわかりませんが、おそらく今回のはSQLでしたほうが良いと思います。
退会済みユーザー

退会済みユーザー

2016/11/10 02:57

c_idがログインした時間と日付を日付ごとにまとめて取得するだけなので、おそらくSQLで行っても負荷はそれほどないので、SQL側で何とかならないか頑張ってみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問