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

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

ただいまの
回答率

88.03%

Db(mysql)の商品テーブルに作成した10個のカラムのフィールドが特定の値に設定されている割合を計算する記述をご教示いただけませんでしょうか。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,525

score 12

Mysql,php,smartyを利用したec系のサイトを作成中です。そのサイトの商品一覧ページの各商品の行にその商品に関するある作業を終了したパーセンテージを算出した結果を表示するカラムを設定したいと考え、その計算に関する記述方法を思案しています。

まず商品テープルtbl_productにjob1からjob10という名称で10個のカラムを設け、そのカラムに1か2の値を設定するようにし、値が2であればその作業は終了したとする設定に致しました。 この作業が10の作業中何個終了したか(tbl_product 内のjob 1~ job 10の10個のカラムの中でフィールドが2に設定されている割合)を計算する記述をどのようなファイル(php、smarty)を使用し、どのように記述すれば宜しいかご教示頂けませんでしょうか。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

SQLだけで十分でしょう。
job 1~ job 10の合計から10引くことで終了した作業の個数がわかるので、以下のように割合を求めることができます。
CREATE TABLE tbl_product( 
  id int auto_increment
  , name varchar (10)
  , job1 int
  , job2 int
  , job3 int
  , job4 int
  , job5 int
  , job6 int
  , job7 int
  , job8 int
  , job9 int
  , job10 int
  , PRIMARY KEY (id)
); 


SELECT
  id
  , name
  , concat( 
    ( 
      job1 + job2 + job3 + job4 + job5 + job6 + job7 + job8 + job9 + job10 - 10
    )  / 10 * 100
    , '%'
  ) result 
FROM
  tbl_product;

さらに、jobを別テーブルに持ち、作業の終了を真偽値で持つことにより、次のようにテーブル構造が簡潔になり、jobの増減にも対応できます。
create table tbl_product( 
  id int auto_increment
  , name varchar (10)
  , PRIMARY KEY (id)
); 

create table tbl_product_jobs( 
  id int
  , job_no int
  , is_finished boolean
  , PRIMARY KEY (id,job_no)
  , FOREIGN KEY (id) REFERENCES tbl_product(id)
);  

SELECT
  tp.id
  , tp.name
  , CONCAT(SUM(tpj.is_finished) / COUNT(*) * 100, '%') 
FROM
  tbl_product tp 
  LEFT JOIN tbl_product_jobs tpj 
    ON tp.id = tpj.id 
GROUP BY
  id;

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/07/14 17:02 編集

    sho_cs様、

    ご指導感謝致します。計算結果をtpl上に表示できました。

    しかしながら、大変申し訳ございませんが、jobが変則的に増減するということ自体を忘れておりました。

    厳密には、ある商品に対して、jobが最低で2あり、それが最大22までになります。Jobが2の時もあれば22の時もあり、つまり2の時は1/2なのか、あるいは10の時は7/10なのか、あるいは22の時は18/22なのかといった具合に一つの商品に対するjobの数が変則的な中で、その内いくつ終了したかを算出したいです。

    上記の条件の場合、頂きました記述の二つ目のSQLは利用可能でしょうか。

    もし可能である場合、その中に tbl_product_jobsのjob_noとありますが、それは一つの商品にある2~22までの間で変則的に変わり得るjobの内でどのように番号を作成するのでしょうか。

    キャンセル

  • 2015/07/14 17:44

    二つ目のSQLは利用可能なはずです。

    番号の作成は一つの商品(同一id)に対してjobの個数分レコードを登録します。
    id=1はjobが2つ、id=2はjobが4つの場合、以下のようになります。
    id=1,job_no=1,...
    id=1,job_no=2,...
    id=2,job_no=1,...
    id=2,job_no=2,...
    id=2,job_no=3,...
    id=2,job_no=4,...

    キャンセル

  • 2015/07/19 11:24

    sho_cs様

    ご指導いただきまして感謝いたします。いろいろな方法で試しておりました。現在tbl_product_jobsにデータを挿入させようとしておりますが、jobの増減に対応する記述自体は機能しているように思われます。本当にありがとうございます。

    キャンセル

-1

私なら以下のようなSQLを作成します。

テーブル構成は他の方が書いたものを想定しています。
--テーブルCREATE文
CREATE TABLE tbl_product( 
  id int auto_increment
  , name varchar (10)
  , job1 int
  , job2 int
  , job3 int
  , job4 int
  , job5 int
  , job6 int
  , job7 int
  , job8 int
  , job9 int
  , job10 int
  , PRIMARY KEY (id)
); 

SQLServer的な書き方をしていますが、雰囲気で。動作確認もしていません^^;
jobが10個なのでjob一つで進捗率が10%として計算を簡単にしています。
対象の商品IDがわかっている場合は条件でidをINで指定する事を想定しています。
SELECT id,COUNT(*) * 10 AS progress_per FROM (
    SELECT id,1 AS job_id,job1 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,2 AS job_id,job2 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,3 AS job_id,job3 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,4 AS job_id,job4 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,5 AS job_id,job5 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,6 AS job_id,job6 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,7 AS job_id,job7 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,8 AS job_id,job8 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,9 AS job_id,job9 AS job_stat from tbl_product --WHERE id IN (...)
    UNION ALL
    SELECT id,10 AS job_id,job10 AS job_stat from tbl_product --WHERE id IN (...)
) job_stat_list
WHERE job_stat = 2
GROUP BY id;

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/07/17 07:43 編集

    HachiyaKouya様

    ご指導いただきまして感謝致します。複雑になり恐縮ですがいくつかご質問がございます。

    ①“--WHERE id IN (...)” を削除して実行するということでよろしいですよね? 
    ②WHERE job_stat = 2は具体的にどうゆうことでしょうか。
    ③idは質問文の簡略化のため使用しただけで、実際はproduct_id。実行の際はproduct_idで実行していますが問題ないですよね。
    ④最後に頂きました記述を実行いたしますと、エラーメッセージもでない代わりに、検索結果が空欄になります。

    行おうとしている事をもう一度確認させて頂きますと、各行に異なる商品が表示される商品一覧ページを作成しよとしております。その各商品の行の列にカラムを作成しようとしております。そのカラムには各々の商品に関する最小で2、最大で22まで変則的に増減する仕事が終了した割合を計算した結果を表示いたします(product_id、name、job1~job22はtbl_product内にある)。

    以上の条件で、sho_cs様から頂きました以下の式は“仕事が10存在し、その10の内いくつ終了したかを計算する“という条件のもと正しい計算結果をmysqlのSQLタブで表示致し、商品一覧ページの各商品の行のカラムにもそれぞれ表示します。

    SELECT product_id , name , concat( ( job1 + job2 + job3 + job4 + job5 + job6 + job7 + job8 + job9 + job10 - 10 ) / 10 * 100 , '%' ) result FROM tbl_product;


    実際実行した記述は以下です。comp_nとcomp_sは必須の仕事で、comp_s1からcomp_sc10は変則的に増減します。

    SELECT product_id,COUNT(*) * 22 AS progress_per FROM (
    SELECT product_id,1 AS job_id,comp_n AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,2 AS job_id,comp_c AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,3 AS job_id,comp_s1 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,4 AS job_id,comp_s2 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,5 AS job_id,comp_s3 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,6 AS job_id,comp_s4 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,7 AS job_id,comp_s5 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,8 AS job_id,comp_s6 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,9 AS job_id,comp_s7 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,10 AS job_id,comp_s8 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,11 AS job_id,comp_s9 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,12 AS job_id,comp_s10 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,13 AS job_id,comp_sc1 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,14 AS job_id,comp_sc2 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,15 AS job_id,comp_sc3 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,16 AS job_id,comp_sc4 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,17 AS job_id,comp_sc5 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,18 AS job_id,comp_sc6 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,19 AS job_id,comp_sc7 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,20 AS job_id,comp_sc8 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,21 AS job_id,comp_sc9 AS job_stat from tbl_product
    UNION ALL
    SELECT product_id,22 AS job_id,comp_sc10 AS job_stat from tbl_product
    ) job_stat_list
    WHERE job_stat = 2
    GROUP BY product_id;

    キャンセル

  • 2015/07/17 11:07

    お返事ありがとうございます。

    以下に回答します。

    > ①“--WHERE id IN (...)” を削除して実行するということでよろしいですよね?
    そうです。
    そうすると、テーブル内の商品全件のデータが抽出されます。
    対象の商品IDが決まっているのであれば各行にWHERE文を指定して商品を限定すると良い、という意図でコメントとして記載しました。

    > ②WHERE job_stat = 2は具体的にどうゆうことでしょうか。
    UNION ALLで連結している各SELECT文は、商品を特定する情報と複数あるjobのうち特定の一つの値を取得するSQLです。
    job状態のカラム名はそれぞれ違うものですので、job_statという別名をつけています。
    このSQLは、1レコードに1商品の全てのjobの状態が横並びになっているものを、商品ごと・ジョブ1つの状態で複数レコードのテーブルとして扱う想定です。

    商品ID,job1,job2,job3...

    というレコードを

    商品ID,job1
    商品ID,job2
    商品ID,job3
    ...

    というテーブルに変換して処理しています。
    その変換後のテーブルからjob各カラムの値が2のものの個数を取得しています。

    > ③idは質問文の簡略化のため使用しただけで、実際はproduct_id。実行の際はproduct_idで実行していますが問題ないですよね。
    はい、問題ありません。
    あくまでもサンプルですので、用途に合わせて最適化してください。

    > ④最後に頂きました記述を実行いたしますと、エラーメッセージもでない代わりに、検索結果が空欄になります。
    テーブルが空、もしくはjob1~10に2が設定されているものが無いのではないかと思います。

    なお、私が記載したSQLはjobが1~10の10個で固定という前提が必要ですので、おっしゃるような2個から22個の範囲内で可変というのであればSQLはもっと複雑になります。
    複雑なSQLを書くのであれば、PHPで処理してそれぞれシンプルにするほうが後々のメンテナンスが楽ではないかと思いますが、PHPと組み合わせての例は。。。例示できるのは早くても明日になるかと^^;

    キャンセル

  • 2015/07/19 11:43 編集

    HachiyaKouya様

    ご指導いただきまして感謝いたします。

    キャンセル

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

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

関連した質問

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

  • トップ
  • PHPに関する質問
  • Db(mysql)の商品テーブルに作成した10個のカラムのフィールドが特定の値に設定されている割合を計算する記述をご教示いただけませんでしょうか。