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

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

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

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

PHP

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

Q&A

解決済

4回答

5901閲覧

PHPでクロス集計したい

takeruwhite

総合スコア8

MySQL

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

PHP

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

0グッド

2クリップ

投稿2017/10/23 15:52

編集2017/10/26 03:54

MySQLのから後述のように抽出したデータを集計してブラウザ上に表示したいのですが、
途中で行き詰ってしまいました。

出力したいイメージのように2行あるデータを集計して1行にするところを
どのようにアプローチすればいいのかが特にわかりません。
アドバイスをどうぞよろしくお願いいたします。

※10/26サンプルのrank一部修正しました。
↓クエリ結果
|term|subject|name|rank|class|
|:--|:--:|--:|
|1|国語|田中|5|1-1|
|1|算数|田中|4|1-1|
|1|英語|田中|3|1-1|
|1|国語|山田|1|1-1|
|1|算数|山田|1|1-1|
|1|英語|山田|1|1-1|
|2|国語|田中|5|1-1|
|2|算数|田中|1|1-1|
|2|英語|田中|1|1-1|
|2|国語|山田|2|1-1|
|2|算数|山田|2|1-1|
|2|英語|佐藤|1|1-1|

↓出力したいイメージ

namesubjectterm1term2trend
田中国語55
田中算数41
田中英語31
山田国語12
山田算数12
山田英語1-
佐藤英語-1

※trend列はterm1とterm2を比較した結果です。
-は9999と見なして、term1<term2の時↓、term1>term2の時↓、 term1=term2の時→を表示する。

PHP

1$class= '1-1'; 2try{ 3 $dbh = new PDO($dsn, $user, $password); 4 $sql = 'select term,subject,name,rank,class from t_scores WHERE class=:class'; 5 6 $statement = $dbh->prepare($sql); 7 $statement->bindValue(':class', $class, PDO::PARAM_STR); 8 $statement->execute(); 9 $result = array(); //初期化 10 11 while($row = $statement->fetch(PDO::FETCH_ASSOC)){ 12 $name = $row['name']; 13 $subject = $row['subject']; 14 $rank = $row['rank']; 15 16 $result[$name][$subject][$term] = $rank; 17 } //while 18 }catch (PDOException $e){ 19 print('Error:'.$e->getMessage()); 20 die(); 21 } 22 $dbh = null;

$resultの中に入れ子の配列にすればうまく行くように思ったのですが、
思うような形でデータを取り出せずに行き詰っています。

解決方法、または考え方をお教えいただきたいです。
よろしくお願いいたします。

【追記】
沢山のアドバイスと不備の修正依頼ありがとうございます。
内容をゆっくりと確認できるのが今夜遅くになりますので、こちらで取り急ぎお礼申し上げます。

帰宅後にじっくりと読ませていただきます。
本当にありがとうございます。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2017/10/23 15:57

テーブル定義とサンプルデータを提示しましょう。誰も答えられませんよ。
yambejp

2017/10/24 04:08

trendのロジックがわからない。全部下向きなら意味がない、term1とterm2は同値になる可能性は?
guest

回答4

0

ベストアンサー

元データ

SQL

1 2create table tbl(term int,subject varchar(20),name varchar(20),rank int,class varchar(20)); 3insert into tbl values 4(1,'国語','田中',5,'1-1'), 5(1,'算数','田中',4,'1-1'), 6(1,'英語','田中',3,'1-1'), 7(1,'国語','山田',1,'1-1'), 8(1,'算数','山田',1,'1-1'), 9(1,'英語','山田',1,'1-1'), 10(2,'国語','田中',1,'1-1'), 11(2,'算数','田中',1,'1-1'), 12(2,'英語','田中',1,'1-1'), 13(2,'国語','山田',2,'1-1'), 14(2,'算数','山田',2,'1-1'), 15(2,'英語','佐藤',1,'1-1'); 16

集計

SQL

1select subject,name 2,sum(case when term=1 then rank else 0 end) as term1 3,sum(case when term=2 then rank else 0 end) as term2 4from tbl group by subject,name 5order by term1 desc,term2 desc 6

追記

mysqlならこれでもよいかも

SQL

1select subject,name 2,sum((term=1)*rank) as term1 3,sum((term=2)*rank) as term2 4from tbl group by subject,name 5order by term1 desc,term2 desc

投稿2017/10/24 01:14

編集2017/10/24 01:31
yambejp

総合スコア114757

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

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

takeruwhite

2017/10/25 15:25

回答ありがとうございました。意図していたものを作ることができました。 SQLをちゃんと使えればシンプルに実現できたのですね。勉強します。
guest

0

仕様がひどいので、適当に解釈しています。
php でやろうとすると無駄が多いですね。。。

php

1<?php 2$t_scores =[ 3 [ 4 'term' => 1, 5 'subject' => '国語', 6 'name' => '田中', 7 'rank' => 5, 8 'class' => '1-1', 9 ], 10 [ 11 'term' => 1, 12 'subject' => '算数', 13 'name' => '田中', 14 'rank' => 4, 15 'class' => '1-1', 16 ], 17 [ 18 'term' => 1, 19 'subject' => '英語', 20 'name' => '田中', 21 'rank' => 3, 22 'class' => '1-1', 23 ], 24 [ 25 'term' => 1, 26 'subject' => '国語', 27 'name' => '山田', 28 'rank' => 1, 29 'class' => '1-1', 30 ], 31 [ 32 'term' => 1, 33 'subject' => '算数', 34 'name' => '山田', 35 'rank' => 1, 36 'class' => '1-1', 37 ], 38 [ 39 'term' => 1, 40 'subject' => '英語', 41 'name' => '山田', 42 'rank' => 1, 43 'class' => '1-1', 44 ], 45 [ 46 'term' => 2, 47 'subject' => '国語', 48 'name' => '田中', 49 'rank' => 1, 50 'class' => '1-1', 51 ], 52 [ 53 'term' => 2, 54 'subject' => '算数', 55 'name' => '田中', 56 'rank' => 1, 57 'class' => '1-1', 58 ], 59 [ 60 'term' => 2, 61 'subject' => '英語', 62 'name' => '田中', 63 'rank' => 1, 64 'class' => '1-1', 65 ], 66 [ 67 'term' => 2, 68 'subject' => '国語', 69 'name' => '山田', 70 'rank' => 2, 71 'class' => '1-1', 72 ], 73 [ 74 'term' => 2, 75 'subject' => '算数', 76 'name' => '山田', 77 'rank' => 2, 78 'class' => '1-1', 79 ], 80 [ 81 'term' => 2, 82 'subject' => '英語', 83 'name' => '佐藤', 84 'rank' => 1, 85 'class' => '1-1', 86 ], 87 [ 88 'term' => 1, 89 'subject' => '英語', 90 'name' => '佐藤2', 91 'rank' => 1, 92 'class' => '1-1', 93 ], 94]; 95 96foreach ($t_scores as $t_score) { 97 $term_1 = null; 98 $term_2 = null; 99 if(isset($result[$t_score['name']][$t_score['subject']]['term_1'])){ 100 $term_1 = $result[$t_score['name']][$t_score['subject']]['term_1']; 101 } 102 if(isset($result[$t_score['name']][$t_score['subject']]['term_2'])){ 103 $term_2 = $result[$t_score['name']][$t_score['subject']]['term_2']; 104 } 105 if($t_score['term']===1){ 106 $term_1 = $t_score['rank']; 107 $trend = '↑'; 108 } 109 if($t_score['term']===2){ 110 $term_2 = $t_score['rank']; 111 $trend = '↓'; 112 } 113 if(isset($term_1) && isset($term_2)){ 114 if($term_1 ==='-' && $term_2 ==='-'){ 115 $trend = '-'; 116 }else if($term_1 === '-'){ 117 $trend = '↓'; 118 }else if($term_2 === '-'){ 119 $trend = '↑'; 120 }else if($term_1 === $term_2){ 121 $trend = '-'; 122 }else if($term_1 > $term_2){ 123 $trend = '↓'; 124 }else if($term_1 < $term_2){ 125 $trend = '↑'; 126 } 127 } 128 $result[$t_score['name']][$t_score['subject']] = [ 129 'term_1' => isset($term_1)?$term_1:'-', 130 'term_2' => isset($term_2)?$term_2:'-', 131 'trend' => isset($trend)?$trend:'-' 132 ]; 133} 134echo '<table>'; 135echo '<tr> 136<th>name</th> 137<th>subject</th> 138<th>term1</th> 139<th>term2</th> 140<th>trend</th> 141</tr>'; 142foreach ($result as $key1 => $vals) { 143 foreach ($vals as $key2 => $val) { 144echo "<tr> 145<td>$key1</td> 146<td>$key2</td> 147<td>{$val['term_1']}</td> 148<td>{$val['term_2']}</td> 149<td>{$val['trend']}</td> 150</tr>"; 151 } 152} 153echo '</table>';
namesubjectterm1term2trend
田中国語51
田中算数41
田中英語31
山田国語12
山田算数12
山田英語1-
佐藤英語-1
佐藤2英語1-

sql を整理するのがまず先ですね。

投稿2017/10/24 01:43

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

takeruwhite

2017/10/25 15:21

あいまいな質問から意図を組んでいただきありがとうございました。 PHPでの書き方勉強になりました。sqlの使い方勉強します。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2017/10/25 22:37

曖昧というか、trend の表現方法が定義されていないこと、理解しています?
guest

0

PHP側で集計するよりかは、SQLで集計した方が良くないでしょうか。

SQL

1select A.name, A.subject, ifnull(T1.rank, '-') as 'term1', ifnull(T2.rank, '-') as 'term2', 2 case when T1.rank < T2.rank then '↑' when T1.rank > T2.rank then '↓' else '-' end as 'trend' 3from 4( 5 select name, subject from t_scores group by name, subject 6) A left join 7( 8 select rank, name, subject, term from t_scores 9) T1 ON A.name=T1.name AND A.subject=T1.subject AND T1.term=1 10left join 11( 12 select rank, name, subject, term from t_scores 13) T2 ON A.name=T2.name AND A.subject=T2.subject AND T2.term=2

投稿2017/10/24 00:39

編集2017/10/24 00:39
ttyp03

総合スコア16998

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

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

takeruwhite

2017/10/25 15:26

SQLをちゃんと使えればシンプルに実現できるのですね。 SQLの使い方勉強していきます。ご回答ありがとうございました。
guest

0

動作環境がないので確認なのですが、現在結果はどうなっていますか?
単純にコードを見ると$termを設定している場所がなかったりしているのですが
これは今実行しているものではないのでしょうか。

投稿2017/10/24 01:25

yuki-saito

総合スコア928

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

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

takeruwhite

2017/10/25 15:28

ご指摘ありがとうございました。 作っているものからサンプルに置き換えてながら書いている際に色々とおかしくなっていました。 お手間とらせて申し訳ありませんでした。
yuki-saito

2017/10/25 21:44

SQLでよかったのですね。 何であっても解決してよかったです????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問