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

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

ただいまの
回答率

91.86%

  • PHP

    12476questions

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

  • MySQL

    3489questions

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

  • CodeIgniter

    191questions

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

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

解決済

回答 2

投稿 2016/11/08 16:16 ・編集 2016/11/10 11:36

  • 評価
  • クリップ 0
  • VIEW 311

shunsuK

score 24

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

array(14) {
  [0]=>
  array(7) {
    ["office_id"]=>
    string(4) "0000"
    ["area_id"]=>
    string(4) "0000"
    ["c_id"]=>
    string(7) "0000000"
    ["date"]=>
    string(10) "2016-10-25"
    ["sum_num"]=>
    string(1) "6"
  }
  [1]=>
  array(7) {
    ["office_id"]=>
    string(4) "0000"
    ["area_id"]=>
    string(4) "0000"
    ["c_id"]=>
    string(7) "0000000"
    ["date"]=>
    string(10) "2016-10-26"
    ["sum_num"]=>
    string(1) "2"
  }
  [2]=>
  array(7) {
    ["office_id"]=>
    string(4) "0000"
    ["area_id"]=>
    string(4) "0000"
    ["c_id"]=>
    string(7) "0000000"
    ["date"]=>
    string(10) "2016-11-01"
    ["sum_num"]=>
    string(1) "4"
  }
  [3]=>
  array(7) {
    ["office_id"]=>
    string(4) "0000"
    ["area_id"]=>
    string(4) "0000"
    ["c_id"]=>
    string(7) "0000000"
    ["date"]=>
    string(10) "2016-11-04"
    ["sum_num"]=>
    string(1) "2"
  }
  [4]=>
  array(7) {
    ["office_id"]=>
    string(4) "0000"
    ["area_id"]=>
    string(4) "0000"
    ["c_id"]=>
    string(7) "0000000"
    ["date"]=>
    string(10) "2016-11-07"
    ["sum_num"]=>
    string(1) "1"
  }
  [5]=>
  array(7) {
    ["office_id"]=>
    string(4) "0000"
    ["area_id"]=>
    string(4) "0000"
    ["c_id"]=>
    string(7) "0000003"
    ["date"]=>
    string(10) "2016-11-01"
    ["sum_num"]=>
    string(1) "2"
  }

 ・
 ・
 ・
}

view側ではforeachで回し

office_id area_id c_id date sum_num
0000 0000 0000000 2016-10-25 6
0000 0000 0000000 2016-10-26 2
0000 0000 0000000 2016-11-01 4
...

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

これを同じ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
...

さらにレコードがない日付は空白が入るようにしたいです。

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_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
...

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

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

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

    クリップした質問はマイページの「クリップ」タブからいつでも見ることができます。

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • hiim

    2016/11/08 16:23

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

    キャンセル

  • shunsuK

    2016/11/08 16:36

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

    キャンセル

  • 退会済みユーザー

    2016/11/08 16:37

    こちらの質問が他のユーザから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 2

checkベストアンサー

0

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

$output = array();
foreach($dbrecords as $record)
{
    if(!isset($output[$record["c_id"]]))
        $output[$record["c_id"]] = array(
            'office_id' =>$record['office_id'],
            'area_id'=>$record['area_id'],
            'items'=>array()
        );

    $output[$record["c_id"]]['items'][] = array(
        'date'=>$record['date'],
        'sum_num'=>$record['sum_num']
    );
}


view側で

foreach($output as $c_id=>$items)
{
    printf("<tr><td>%s</td><td>%s</td><td>%s</td>",$c_id,$items['office_id'],$items['area_id']);

    foreach($items['items'] as $key=>$item)
    {
        printf("<td>%s</td><td>%s</td>",$item['date'],$item['sum_num']);
    }

    // ここで最大数に満たないレコードのtd埋めするなどの処理


    echo('</tr>');
}

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

投稿 2016/11/08 17:12

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/11/10 11: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>にあたる部分とそれ以外は別の配列にそれぞれ格納するといった方法を考えたほうが良いのでしょうか?

    キャンセル

  • 2016/11/10 11:40

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

    キャンセル

  • 2016/11/10 11:46

    御回答ありがとうございます。

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

    キャンセル

  • 2016/11/10 11:50

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

    キャンセル

  • 2016/11/10 11:57

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

    キャンセル

0

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

create table tbl(a int,b int,c int,d date,e int);
insert 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)


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

drop procedure if exists view;
delimiter //
create procedure view()
begin
declare x1,x2,x3,x5 int;
declare x4 date;
declare done int default 0;
declare cur cursor for
select a,b,c,d,e from tbl;
declare continue handler for sqlstate '02000' set done = 1;
set @a:=(select concat('`',group_concat(distinct d order by d asc separator '` int null,`'),'` int null') from tbl);
set @sql=concat('create temporary table tmp_tbl(`a` int,`b` int,`c` int,',@a,',unique(`a`,`b`,`c`))');
prepare stmt from @sql;
execute stmt;
open cur;
repeat
fetch cur into x1,x2,x3,x4,x5;
set @sql=concat('insert into tmp_tbl(a,b,c,`',x4,'`) values("',x1,'","',x2,'","',x3,'","',x5,'") ');
set @sql=concat(@sql,'on duplicate key update `',x4,'`=',x5);
prepare stmt from @sql;
execute stmt;
until done end repeat;
close cur;
select * from tmp_tbl;
end
//
delimiter ;

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

call view();

投稿 2016/11/08 20:51

編集 2016/11/08 20:59

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/11/10 11:42

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

    キャンセル

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

ただいまの回答率

91.86%

関連した質問

  • 解決済

    配列をループで取り出したいPHP

    下記の配列をforeachで取り出したのですが、どのようなコードを書けばいいですか? $iの部分を0から順に取り出したいです。 <?php foreach ($price as

  • 解決済

    cakephpでカレンダーにデータ表示

    cakephpの2.6.7 phpは5.6で カレンダーを表示させて、DB内の合計を表示させたいのですが、 なにかいい方法ありますでしょうか。 プラグインでもいいです。

  • 解決済

    多次元配列Aを配列Bの順を条件にして並べ替えたい

    以下のように配列Bを条件に多次元配列Aを並べ替えたいです。 何かいい方法はあるでしょうか。 //多次元配列 $arrayA = array( arr

  • 解決済

    縦型のカレンダーを出力したい PHP

    最終的には画像のように送信ボタンを押したら、選択年月が曜日と合わせて テーブルで出力されるカレンダーを作りたいのですが、 月初の曜日を月末まで連続して出力する処理の書き方がわか

同じタグがついた質問を見る

  • PHP

    12476questions

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

  • MySQL

    3489questions

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

  • CodeIgniter

    191questions

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

閲覧数の多いPHPの質問