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

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

ただいまの
回答率

87.34%

データベースから値を取得し、phpで表に表したい。

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,359

score 13

前提・実現したいこと

生徒が課題を提出し、教員は課題ごとに提出状況を確認する。というものを作成しております。
今回、生徒が出した課題を「課題番号」「提出数」「未提出数」と表にしたいです。
課題が1から3まであるとして、

kadai_num 提出数 未提出数
1 3 1
2 4 2

のような形にしたいです。

kadaiテーブル
CREATE table kadai{
id int(11) AUTO_INCREMENT
kadai_num int(11)
hyoka int(11) NULL
comm text
kamoku_id int(11)
user int(11)
teisyutsu int(11) DEFAULT 0
}
です。
評価は1が○、0が△、NULLが×。
提出は1が提出、0が未提出となっています。

該当のソースコード

<?php
$dsn= "localhost";
$username = "root";
$password = "";
$pdo = new PDO($dsn, $username, $password);

$query ='SELECT DISTINCT kadai_num
         FROM kadai';
$stmt = $pdo->query($query);
$rows = $stmt->fetchAll();

$sql = 'SELECT count(*) 
        from kadai
        WHERE teisyutsu = 1'; //出している数
$stmt2 = $pdo->query($sql);
$test = $stmt2->fetchColumn();

$sql = 'SELECT count(*) 
        from kadai
        WHERE hyoka IS NULL'; //出していない数
$stmt3 = $pdo->query($sql);
$test2 = $stmt3->fetchColumn();

?>
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8mb4">
        <link rel="stylesheet" type="text/css" href="css/default.css">
    </head>
    <body>
    <table border="2">
    <tr>Web</tr>
    <th>課題番号</th>
    <th>提出済み</th>
    <th>未提出</th>
        <?php

        foreach($rows as $row){
            echo "<tr>";
            echo "<td>{$row['kadai_num']}</td>";
            echo "<td>{$test}</td>";
            echo "<td>{$test2}</td>";
            echo "</tr>";
            }
        ?>
        </table>
    </body>

</html>

表示結果

イメージ説明

 

自身の知識が未熟なため
・課題1の提出数と未提出数が、課題2以降にも表示されている(SQL文,phpから間違っているが、改善方法がわからない)
→kadai_numごとに提出数と未提出数を表示させたい。
・表示結果では提出4、未提出3となっているがテーブルに全部で7つはいっており、そのうちkadai_numが1なのは3つのみ。(kadaiテーブルすべてが出てきている。)
→解決いたしました。

以上の2つがわかりません。
ご意見、ご教授お願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • m.ts10806

    2019/08/05 10:34

    質問本文を更新してください。
    > 提出は1が提出、0が未提出となっています。
    これだとhyoka IS NULLだと「提出はされたけど未評価」か「提出すらされてない」のか判断できないのでteisyutsuだけで「提出済み」「未提出」を判断すれば良いのでは?

    キャンセル

  • albedo615

    2019/08/05 11:07

    ありがとうございます。更新いたしました。
    teisyutsuのカラムを追加した後、hyoka IS NULLの部分を更新しておりませんでした。
    teisyutsuだけで「提出済み」と「未提出」を判断するようにしました。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2019/08/05 12:07

    NULLは特別な値というか状態なので、そこに意味をもたせてしまうよりかは、ちゃんと2 1 0や1 0 -1などにするべきかと。IS NULLやIS NOT NULLの絞り込みって昔はインデックス効かなかった気がするけど、今はどうなんですかね。「「提出はされたけど未評価」か「提出すらされてない」のか判断できない」にもつながるので、実用的な値の見直しが必要だと思います。

    キャンセル

回答 2

+2

・課題1の提出数と未提出数が、課題2以降にも表示されている(SQL文,phpから間違っているが、改善方法がわからない)

$testも$test2も課題番号で絞られていないので
$testは「teisyutsu = 1で絞り込まれた全件の合計件数」が取得されます。
$test2は「hyoka IS NULLで絞り込まれた全件の合計件数」が取得されます。

SQLはPHPからすると外部の仕組みですので、「どういう情報が取得できるか」は
DBに対して直に実行して確認すると良いです。

ですので、取得できているのは「課題1の提出数と未提出数」ではありません。全部です。

もちろん、$rowsを取得しているSQLも確認すべきですね。

根本解決

テーブル定義が不明ですがGROUP BYとサブクエリ使ってSQL一発で出せそうに思います。

※構文チェックだけ通った未検証コード

SELECT
    a.kadai_num,
    COUNT(t.kadai_num) AS teisyutsu_count,
    COUNT(h.kadai_num) AS miteisyutsu_count
FROM
    kadai a
LEFT JOIN(
    SELECT
        kadai_num,
        COUNT(*)
    FROM
        kadai
    WHERE
        teisyutsu = 1
    GROUP BY
        kadai_num
) t
ON
    a.kadai_num = t.kadai_num
LEFT JOIN(
    SELECT
        kadai_num,
        COUNT(*)
    FROM
        kadai
    WHERE
        -- hyoka IS NULL
        teisyutsu = 0
    GROUP BY
        kadai_num
) h
ON
    a.kadai_num = h.kadai_num
GROUP BY
    a.kadai_num

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/05 11:54

    hyoka IS NULLの部分を更新し、$test,$test2のSELECT文にGROUP BYを追加したところ、kadai_numが1の提出数2、未提出数1となりkadai_numの合計となりました。ありがとうございます。

    課題2以降の提出・未提出の表示はforeach文の$test,$test2の変更となるのでしょうか?

    キャンセル

  • 2019/08/05 11:57

    むしろSQLを分ける意味ってありません。
    私が回答に提示したSQLを見ると分かりますが、1つのSQLで提出・未提出のGROUP BYまで全てやりきったうえで出しています。
    出したい情報は課題番号と密接に関わるものですから、SQLを分けることによってデータ同士の関係性が薄くなるのと、何度もSQLを発行・実行することによる負荷を懸念します。
    SQLも結構便利なので、できればアプリケーション側では「表示すればいいだけ」のデータをSQLで作ってしまうのが最も効率的です。

    キャンセル

+1

提出数についてはteisyutsu = 1で拾えると思いますが
未提出は本当にteisyutsu = nullのデータを置いてあるのでしょうか?
(課題を出した時点で全員未提出状態にしてデータを投入しているかどうか?)

もし、上記のような運用方法なら

SELECT kadai_num,sum(teisyutsu = 1) as 提出数,sum(hyoka IS NULL) as 未提出数
FROM kadai
GROUP BY kadai_num

対象人数から提出済み数を引くだけでよいかもしれません。
対象人数は普通別途ユーザーテーブルなどで管理していると思います。

追記

考え方からするとkadaiテーブルで提示されている処理は
kadaiを管理するのではなくkadai_userの中間テーブルで、別途kadaiとuserを
管理するテーブルがあるとよりSQL的になります

参考)
課題=3つ、ユーザー=7人いたとして、その連携状態が
課題とユーザーの組み合わせ
(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,4),(2,5),(3,1),(3,5),(3,6)
について提出済みとします

create table kadai_user(
id int(11) primary key auto_increment,
kadai_id int(11),
user_id int(11),
teisyutsu int(11) default 0
);

insert into kadai_user(kadai_id,user_id)
values
(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),
(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7);

update kadai_user set teisyutsu=1
where concat(kadai_id,",",user_id) in (
"1,1","1,2","1,3","1,4",
"2,1","2,2","2,4","2,5",
"3,1","3,5","3,6");
  • 集計
select kadai_id,sum(teisyutsu=1) as 提出済,sum(teisyutsu=0) as 未提出
from kadai_user 
group by kadai_id

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/05 10:21

    未提出はteisyutsuのデフォルト値を0にしており、課題を出した時に1にすると考えていました。

    キャンセル

  • 2019/08/05 11:06 編集

    そうなると「sum(teisyutsu=0) as 未提出数」でやってください
    nullを前提とした仕組みはパフォーマンスを落とす可能性があります
    ※書き間違い修正しました

    キャンセル

  • 2019/08/05 11:42

    サンプル追記しておきました

    キャンセル

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

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

関連した質問

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