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

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

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

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

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

Q&A

解決済

3回答

523閲覧

PHPでレコードの検索

gsuisk

総合スコア72

MySQL

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

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

0グッド

0クリップ

投稿2017/09/12 13:58

編集2017/09/13 08:47

質問を訂正しました。

PHPとMySQLを使って以下のような機能を実装したいです。

難易度、科目名、講師名の3つのカラムを持つテーブルがあり、いくつかのレコードが格納されています。

ここで、このテーブルからレコードを検索して、一致するものを抽出したいです。

ちなみに、「難易度」は<select>タグでプルダウンメニューとして設定し、
(「易」「普通」「難」から選ぶ)
「科目名」と「講師名」は<input type="text">で設定します。

検索の条件は

検索者は「難易度」の選択のみが必須で、「科目名」と「講師名」の入力は任意。

できなくて困っていることは

例えば「数学」として格納されているデータを抽出するのに、 「数」では引っかかってくれるのですが、「数学者」では引っかからないことです。

ポストされたデータは、難易度が$difficulty、科目名が$subject、講師名が$teacherに代入してあります。。テーブル名はtableです。

汚いコードですが書いてみたものです。

PHP

1 if($difficulty=='易'){ 2 3 $sql = "SELECT * FROM table 4 WHERE (difficulty='易') AND (subject LIKE(:subject)) AND (teacher 5 LIKE(:teacher))"; 6 7 $stm = $pdo->prepare($sql); 8 $stm->bindValue(':subject', "%{$subject}%", PDO::PARAM_STR); 9 $stm->bindValue(':teacher', "%{$teacher}%", PDO::PARAM_STR); 10 11 }else if($difficulty=='普通'){ 12 //上と同じ処理 13 }else{ 14 //上と同じ処理 15 }

WHEREをどのようにすれば、入力文字が実際のデータの文字列を超えていても抽出できるのでしょうか?
また選択必須の難易度$difficultyは条件分岐しなくてもできるでしょうか?

複雑で面倒な質問で本当にすみません。もしわかる方がいれば知恵を拝借させてください。

よろしくお願いします。

以下追記です。________________________________________________________________________

$stm->bindValue(':subject1', "%{$subject}%", PDO::PARAM_STR); $stm->bindValue(':subject2', "{$subject}%", PDO::PARAM_STR);

のように、subject1とsubject2をORではできないのでしょうか?(試しましたが動作しませんでした。)

"{$subject}%"とすれば格納されている文字列に余計なものが続いて入力されていても抽出されると思ったのですが、、

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

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

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

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

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

guest

回答3

0

php

1<?php 2ini_set('display_errors', 1); 3error_reporting(E_ALL); 4 5$options = [ 6 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 7 , PDO::ATTR_EMULATE_PREPARES => true 8]; 9$pdo = new PDO($dsn, $username, $password, $options); 10 11$sql = "SELECT * FROM table WHERE 1 "; 12 13$data = []; 14 15if(!is_null($difficulty)){ 16 $sql.="and difficulty = :difficulty "; 17 $data[':difficulty'] = $difficulty; 18} 19 20if(!is_null($subject)){ 21 $sql.="and (subject like CONCAT('%', :subject, '%') OR CONCAT('%', subject, '%') like :subject) "; 22 $data[':subject'] = $subject; 23} 24 25if(!is_null($teacher)){ 26 $sql.="and (teacher like CONCAT('%', :teacher, '%') OR CONCAT('%', teacher, '%') like :teacher) "; 27 $data[':teacher'] = $teacher; 28} 29 30$stmt = $pdo->prepare($sql); 31$stmt->execute($data);

投稿2017/09/13 08:59

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

gsuisk

2017/09/13 09:17

Invalid parameter number: parameter was not defined というエラーがでてしまいます...
退会済みユーザー

退会済みユーザー

2017/09/13 09:36

少しは調べましょうね。
gsuisk

2017/09/13 09:53

すみません、、参考になりました。ありがとうございました。
guest

0

ベストアンサー

流れ的にはこうします
※追記:スペースの抜けだけ修正しました

PHP

1$sql = "SELECT * FROM table WHERE 1 "; 2$data=[]; 3if(!is_null($difficulty)){ 4 $sql.="and difficulty=? "; 5 $data[]=$difficulty; 6} 7if(!is_null($subject)){ 8 $sql.="and subject like ? "; 9 $data[]="%".$subject."%"; 10} 11if(!is_null($teacher)){ 12 $sql.="and teacher like ? "; 13 $data[]="%".$teacher."%"; 14} 15$stmt = $pdo->prepare($sql); 16$stmt->execute($data);

ただし前方後方一致はパフォーマンスがでないので注意が必要

修正版

PHP

1$sql = "SELECT * FROM table WHERE 1 "; 2$data=[]; 3if(!is_null($difficulty)){ 4 $sql.="and difficulty=? "; 5 $data[]=$difficulty; 6} 7if(!is_null($subject)){ 8 $sql.="and ( 0 "; 9 $sql.="or subject like concat('%',?,'%') "; 10 $data[]=$subject; 11 $sql.="or ? like concat('%',subject,'%') "; 12 $data[]=$subject; 13 $sql.=") "; 14} 15if(!is_null($teacher)){ 16 $sql.="and ( 0 "; 17 $sql.="or teacher like concat('%',?,'%') "; 18 $data[]=$teacher; 19 $sql.="or ? like concat('%',teacher,'%') "; 20 $data[]=$teacher; 21 $sql.=") "; 22} 23$stmt = $pdo->prepare($sql); 24$stmt->execute($data); 25

投稿2017/09/13 00:23

編集2017/09/13 09:28
yambejp

総合スコア114769

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

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

gsuisk

2017/09/13 08:18

SQLSTATE[42000]: Syntax error or access violation: 1064 ... use near 'table WHERE 1 and difficulty=?and subject like ?and teacher like ?' at line 1 こんなエラーが出てしまいます。
yambejp

2017/09/13 08:32 編集

とりあえずスペースの抜けがあったので追記しました。 テーブル名はtableになっていますが、正しいものを利用してください また、もしテーブル名に「table」という予約語を使っている場合は from `table`のようにバックスラッシュでかこってください
gsuisk

2017/09/13 08:42

ありがとうございます。 訂正されたもので試してみたのですが、やはり「数学」を抽出するのに「数学者」や「数学1」など余計な文字列を入力すると抽出してくれません、、、
gsuisk

2017/09/13 08:48

実現したいことのイメージを質問に追記したのでよければ読んでいただきたいです。
yambejp

2017/09/13 08:58

すみません、発想が逆だったみたいです。 「数」から「数学」でも、「数学者」から「数学」でも どちらもヒットするような内容を追記しておきました
gsuisk

2017/09/13 09:13

ありがとうございます。 何度も本当に申し訳ないのですが、、 use near 'subject like concat('%',?,'%') or concat('%',subject,'%') like ? ) and ( 0or teacher' at line 1 というエラーが出てしまいます...
yambejp

2017/09/13 09:16

こちらこそナン度も同じミスで申し訳ないです 0の後ろに半角スペースが抜けてたので足しときました 再チャレンジお願いします
gsuisk

2017/09/13 09:23

エラーはでないのですが、やはり「数学者」や「数学1」等と入力すると引っかかりません... 他の回答者さんのでもうまくいかなくて...SQL文でないところで不具合が起こっているのですかね...? 私の知識不足で他の不具合を発見できずにいるのかもしれません(汗)
yambejp

2017/09/13 09:29

すみません、完全に記載ミスがありました 修正しました
gsuisk

2017/09/13 09:38

できました!!助かります!何度も親切に本当にありがとうございました!
guest

0

MySQLでしか使えないと思いますが、下記のようにCONCAT(文字列結合)SQL文を使って書くことができます。しかし、決まった仕様なのであればテキストボックスではなく、セレクトボックスのような選択肢にすればこのようなことをしなくても良いと思います。

  • subject LIKE '%数%' OR
  • '数学者' LIKE '%数学(subject)%'

sql

1SELECT * FROM table 2WHERE ( 3 difficulty = :difficulty AND 4 subject LIKE CONCAT('%',:subject,'%') AND 5 teacher LIKE CONCAT('%',:teacher,'%') 6) OR ( 7 difficulty = :difficulty AND 8 :subject LIKE CONCAT('%',subject,'%') AND 9 :teacher LIKE CONCAT('%',teacher,'%') 10)

PHPのプレースホルダのバインドは、下記のようにします。テキストボックスが空の時は、条件分岐でSQL文とプレースホルダのバインドを分けて書きます。

php

1 $stm->bindValue(':difficulty', $difficulty, PDO::PARAM_STR); 2 $stm->bindValue(':subject', $subject, PDO::PARAM_STR); 3 $stm->bindValue(':teacher', $teacher, PDO::PARAM_STR);

きちんとやるには、日本語の形態要素解析か単語辞書検索のようなロジックが必要になります。

投稿2017/09/12 19:18

編集2017/09/13 11:35
Tomak

総合スコア1652

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

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

yambejp

2017/09/13 01:39

LIKE '%:subject%'は、よくないかもしれませんね LIKE CONCAT('%',:subject,'%') とするか bidValue側で先に’%’をつけたほうがよいでしょう
Tomak

2017/09/13 07:26

>LIKE '%:subject%'は、よくないかもしれませんね >LIKE CONCAT('%',:subject,'%') とするか >bidValue側で先に’%’をつけたほうがよいでしょう 確かにそうですね。。。(汗;;) 回答を修正しておきます。
gsuisk

2017/09/13 08:21

エラーはでないのですが、何を入力しても検索結果なしになってしまいます、、、
gsuisk

2017/09/13 09:52

解決しました。ありがとうございました。
Tomak

2017/09/13 11:37

修正が遅くなりました。。。解決したということで良かったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問