-PR-
  • 困ってます
  • 質問No.8648072
解決
済み

SQL文の書き方をご教授お願い致します。

  • 閲覧数186
  • ありがとう数15
  • 気になる数0
  • 回答数5
  • コメント数0

お礼率 58% (39/67)

<th>物件種別</th>


<td>
<input type="checkbox" name="kid[]" value="1" <?php if( $_REQUEST["kid"] == "1" ){ print( 'checked' ); } ?>/>
温泉
<input type="checkbox" name="kid[]" value="2" <?php if( $_REQUEST["kid"] == "2" ){ print( 'checked' ); } ?>/>
キャンペーン
<input type="checkbox" name="kid[]" value="3" <?php if( $_REQUEST["kid"] == "3" ){ print( 'checked' ); } ?>/>
イベント
<input type="checkbox" name="kid[]" value="4" <?php if( $_REQUEST["kid"] == "4" ){ print( 'checked' ); } ?>/>
特別室<br />
<input type="checkbox" name="kid[]" value="5" <?php if( $_REQUEST["kid"] == "5" ){ print( 'checked' ); } ?>/>
和室
<input type="checkbox" name="kid[]" value="6" <?php if( $_REQUEST["kid"] == "6" ){ print( 'checked' ); } ?>/>
喫煙室</td>

</tr>
<tr>

//まずこのSQL文でt_hotelsのテーブルとt_hotel_kodawariを結合します

$sql="SELECT t_hotels.id,t_hotels.hotel_name,t_hotels.price,t_hotels.address,t_hotel_kodawari.id,t_hotel_kodawari.kid FROM t_hotels JOIN t_hotel_kodawari USING(id) WHERE 1
";

テーブル t_hotel_kodawari

id kid
------------
1 1
1 2
1 4
2 1
2 5
3 2
4 3
4 6
5 2
5 3
6 1
7 2



テーブルt_hotels

id hotel_name price address
-----------------------------------------------------
1 Aホテル 10000 栃木県・・・
2 Bホテル 12000 栃木県・・・
3 Cホテル 9000 千葉県・・・
4 Dホテル 10000 千葉県・・・
5 Eホテル 15000 愛知県・・・
6 Fホテル 30000 東京都・・・
7 Gホテル 40000 神奈川県・・・



テーブルt_hotels とt_hotel_kodawariをJOIN USINで結合して表示

id hotel_name price address id kid
-------------------------------------------------------------------
1 Aホテル 10000 栃木県・・・ 1 1
1 Aホテル 10000 栃木県・・・ 1 2
1 Aホテル 10000 栃木県・・・ 1 4
2 Bホテル12000 栃木県・・・ 2 1
2 Bホテル12000 栃木県・・・ 2 5
3 Cホテル 9000 千葉県・・・ 3 2
4 Dホテル 10000 千葉県・・・ 4 3
4 Dホテル 10000 千葉県・・・ 4 6
5 Eホテル 15000 愛知県・・・ 5 2
5 Eホテル 15000 愛知県・・・ 5 3
6 Fホテル 30000 東京都・・・ 6 1
7 Gホテル40000 神奈川県 7 2


$condition = array();

//仮にkid1が一つ選択されたら


まず
if( !empty( $_POST["kid"] )){
for($i=0; $i<count($_REQUEST["kid"]); $i++) {
$tmpKey = "kid".$i;
$sql .= " and kid = :".$tmpKey;
$condition[$tmpKey] = $_REQUEST["kid"][$i];

var_dump($sql);

}
}
で絞り込まれSQL文が作られ、

var_dump($sql);でSQL文を表示させると

string(184) "SELECT t_hotels.id,t_hotels.hotel_name,t_hotels.price,t_hotels.address,t_hotel_kodawari.id,t_hotel_kodawari.kid FROM t_hotels JOIN t_hotel_kodawari USING(id) WHERE 1 and kid = :kid0" の結果によって、

kid1を選択するとホテルA,B,Fが表示されます。

でkidがまずandで絞り込まれます。
ですが、もう二つ目選択すると

string(184) "SELECT t_hotels.id,t_hotels.hotel_name,t_hotels.price,t_hotels.address,t_hotel_kodawari.id,t_hotel_kodawari.kid FROM t_hotels JOIN t_hotel_kodawari USING(id) WHERE 1 and kid = :kid0" string(200) "SELECT t_hotels.id,t_hotels.hotel_name,t_hotels.price,t_hotels.address,t_hotel_kodawari.id,t_hotel_kodawari.kid FROM t_hotels JOIN t_hotel_kodawari USING(id)「 WHERE 1 and kid = :kid0 and kid = :kid1"」 で
-------------------------------------------


二重にand で絞られてしまい何も出てきません。希望としては二回目の選択からkidはor条件にすれば仮にkid1,kid2ホテルA,B,C,E,F,Gと両方を含む表示を実現したいのですが、
実際はSQLの表記の方法をネットや本で調べたのですが、分からない状態です。ご教授いただけたらと思います。

なお、私の希望通りの方法ではなくても実現できれば大丈夫です。

どうかよろしくお願い致します。
  • 回答数5
  • 気になる数0

質問者が選んだベストアンサー

  • 回答No.5
レベル14

ベストアンサー率 51% (3827/7415)

あ・・・$rowsの宣言がされてないですね

while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$rows[]=$row;
};

の直前に
$rows=array();

としといた方がいいかもしれません。
補足コメント
sinto58167

お礼率 58% (39/67)

まさに
foreach((array) $rows as $row ){
にして$rows=array();も表記したら
エラーが消えました。

エラーの行番号もyambejp様の仰る通りでした。

あと検索結果が項目意外、表示されないです。
カラムが合ってないのでしょうか?

t_hotels


id hotel_name price_min price_max address
1 HOTELA 10000 15000 栃木県・・・
2 HOTELB 12000 20000 栃木県・・・
3 HOTELC 9000 18000 千葉県・・・
4 HOTELD 20000 25000 千葉県・・・
5 HOTELE 15000 30000 愛知県・・・
6 HOTELF 30000 35000 東京都・・・
7 HOTELG 40000 43000 神奈川県・・・

t_hotel_kodawari

hid kid
1 1
1 3
1 4
2 1
2 5
3 2
4 3
4 6
5 2
5 3
6 1
7 2

合ってると思うのですが。

以下、print_rの返す内容です。

SELECT t1.* FROM t_hotels as t1 INNER JOIN (SELECT DISTINCT hid FROM t_hotel_kodawari WHERE kid in (?,?)) as t2 ON t1.id=t2.hid WHERE 1 AND address LIKE ? AND price BETWEEN ? AND ?
Array ( [0] => 1 [1] => 5 [2] => %千葉県% [3] => 6000 [4] => 10000 ) Array ( )

原因は何が考えられますでしょうか?

何卒よろしくお願い致します。
投稿日時 - 2014-06-23 23:52:53
お礼コメント
sinto58167

お礼率 58% (39/67)

出力できない理由がわかりました!

単純なミスでした。$rowで出力しなければならないのが$resultになっていました!

お騒がせいたしました。
yambejp様には本当になんて言っていいのかわからないくらい感謝しております!
今回のような検索機能は実装できたのがはじめてなので、感無量です!

長きに渡って疑問がようやく解決されました。
yambejp様、そして他の方々も私のような素人の相談に乗っていただき本当にありがとうございました!
投稿日時 - 2014-06-24 05:15:37
  • ありがとう数0
-PR-
-PR-

その他の回答 (全4件)

  • 回答No.1
レベル14

ベストアンサー率 38% (1791/4713)

コンピューター カテゴリマスター
カテゴリマスターとは?
$sql .= " and kid = :".$tmpKey; を $sql .= " or kid = :".$tmpKey; にするだけでは? ...続きを読む
$sql .= " and kid = :".$tmpKey;

$sql .= " or kid = :".$tmpKey;
にするだけでは?
お礼コメント
sinto58167

お礼率 58% (39/67)

t_ohta様、今回もアドバイス感謝いたします。
誠にありがとうございます。

orに変更したのですが、重複して表示されていて上からAホテルが3つ、Bホテル2つが、Cは1つ、
Dが2つ、Eが2つ、Fが1、Gが1つ縦に並んだ状態になってしまいます。
重複表示しないようにしたいのですが、なかなかうまくいきません。

HTMLの表示のさせかたか、MySQL並べ方が良くないのでしょうか?要因はどこにあるかわからない状態です。
質問ばかりで申し訳ありません。
投稿日時 - 2014-06-22 15:27:17
  • ありがとう数0
  • 回答No.2
レベル14

ベストアンサー率 51% (3827/7415)

たとえばこんな感じ SELECT t1.* FROM t_hotels as t1 INNER JOIN (SELECT hid FROM t_hotel_kodawari WHERE kid in (1,3,4)) as t2 ON t1.id=t2.hid t_hotel_kodawariをkidの値で絞り込んでからINNER JOINするとよいでしょう PHPの処理的には $sql=&quo ...続きを読む
たとえばこんな感じ

SELECT t1.* FROM t_hotels as t1
INNER JOIN (SELECT hid FROM t_hotel_kodawari WHERE kid in (1,3,4)) as t2
ON t1.id=t2.hid

t_hotel_kodawariをkidの値で絞り込んでからINNER JOINするとよいでしょう

PHPの処理的には

$sql="SELECT t1.* FROM t_hotels as t1 ";
if(isset($_REQUEST["kid"]) and is_array($_REQUEST["kid"])){
$sql.="INNER JOIN (SELECT hid FROM t_hotel_kodawari WHERE kid in ("
$sql.=implode(",",array_fill(0,count($_REQUEST["kid"]), '?'))
$sql.=") as t2 ON t1.id=t2.hid ";
}

のようにSQL文をつくっておき、あとからkidの値を?に当てはめればいいでしょう
補足コメント
sinto58167

お礼率 58% (39/67)

yambejp様、いつもご教授くださり大変感謝しております。ありがとうございます。
kidの部分まで絞り込んで値を入れていくSQL文はわかりませんでした。

私の読んでいる本には書いていないことばかりで理解することがかなり難しいです。
わたしにもっと理解力があればといつも思います。

Parse error: syntax error, unexpected '$sql' (T_VARIABLE) inという表示が出てしまいます。

原因がどこにあるのか力不足でわからない状態です。
私なりに考えたのですが、$conditionに何も無いからかもしれません。
もし別の原因で間違っていたら申し訳ありません。


もしよろしければ
$condition[$tmpKey] = $_REQUEST["kid"][$i];
だとか

if( !empty( $_REQUEST["address"] ) ){
$sql = $sql . " and ( address like :address ) ";
$condition[":address"] = "%{$_REQUEST["address"]}%";
}

というような感じで
$conditionに値(プレースホルダでしょうか?)を入れるみたいなプログラムの書き方を教えてもらえないでしょうか?

いつも申し訳ありません。

念のため他の受け手の方のプログラムさらしておきます。

今回も勉強させていただき、ありがとうございました。

if( !empty( $_REQUEST["price_min"] ) ){
$sql = $sql . " and price >= :price_min " ;
$condition[":price_min"] = $_REQUEST["price_min"];

var_dump($sql);

}

if( !empty( $_REQUEST["price_max"] ) ){
$sql = $sql . " and price <= :price_max ";
$condition[":price_max"] = $_REQUEST["price_max"];
}

if( !empty( $_REQUEST["address"] ) ){
$sql = $sql . " and ( address like :address ) ";
$condition[":address"] = "%{$_REQUEST["address"]}%";


}



$statement = $pdo->prepare( $sql );
$statement->execute( $condition );
$results = $statement->fetchAll();
投稿日時 - 2014-06-23 15:05:30
  • ありがとう数0
  • 回答No.3
レベル14

ベストアンサー率 51% (3827/7415)

じゃ、こんな感じで・・・ カラムの名称などは適当にあわせてください <?PHP //初期設定 //username,$password,$dbnameは適当に $dsn = 'mysql:host=localhost; dbname='.$dbname; $data=array(); $sql = "SELECT t1.* FROM t_hotels as t1 & ...続きを読む
じゃ、こんな感じで・・・
カラムの名称などは適当にあわせてください

<?PHP

//初期設定
//username,$password,$dbnameは適当に
$dsn = 'mysql:host=localhost; dbname='.$dbname;
$data=array();
$sql = "SELECT t1.* FROM t_hotels as t1 ";
$flag=true;

//kid絞り込み
if(isset($_REQUEST["kid"]) and is_array($_REQUEST["kid"])){
$sql.="INNER JOIN (SELECT DISTINCT hid FROM t_hotel_kodawari WHERE kid in (";
$sql.=implode(",",array_fill(0,count($_REQUEST["kid"]), '?'));
$sql.=")) as t2 ON t1.id=t2.hid ";
$data=array_merge($data,$_REQUEST["kid"]);
$flag=false;
}

//WHERE句作成
$sql.= "WHERE 1 ";

//住所絞り込み
if(isset($_REQUEST["address"]) and $_REQUEST["address"]!==""){
$sql.="AND address LIKE ? ";
array_push($data,"%".$_REQUEST["address"]."%");
$flag=false;
}

//価格絞り込み
if(isset($_REQUEST["price_min"]) and $_REQUEST["price_min"]!==""){
$price_min=str_replace(",","",$_REQUEST["price_min"]);
}else{
$price_min=0;
}
if(isset($_REQUEST["price_max"]) and $_REQUEST["price_max"]!==""){
$price_max=str_replace(",","",$_REQUEST["price_max"]);
}else{
$price_max=1000000;
}
if(isset($_REQUEST["price_min"]) or isset($_REQUEST["price_max"])){
$sql.="AND price BETWEEN ? AND ? ";
array_push($data,$price_min,$price_max);
$flag=false;
}

//なにもパラメータがないときは表示しない
if($flag) $sql.="AND 0 ";;

//参考
print $sql."<br>";
print_r($data);

//実行
$pdo = new PDO($dsn,$username,$password);
$stmt = $pdo->prepare( $sql);
$stmt->execute($data);

while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$rows[]=$row;
};
print_r($rows);
補足コメント
sinto58167

お礼率 58% (39/67)

いつも教えていただき本当に感謝いたします。
あともう一息でできるのではと思っています。
ありがとうございます。
もしうまくいったらお礼をしたいくらいです。
まさかここまで教えてもらえるとは思ってもいませんでした。
いつも素人の質問でもうしわけありませんが、
このようなエラーが出てしまいます。
配列の出し方が問題だと思うのですが、どのようにプログラムを書けばいいのかわかりません。
一部前半の部分を省略したコードをさらしますので、
どう書けば良いのか教えていただきたいです。
ただ教えてくれるかどうかは全然自由なのでスルーしてもらっても大丈夫です。

Warning: Invalid argument supplied for foreach() in

<body id="S03-10">
<div id="main">

<h1>ビジネスホテルの条件検索</h1>

<form name="search_form" action="xxxxx.php" method="post" >
<input type="hidden" name="cmd" value="search" />
<table>

<tr>
<th>物件種別</th>

<td>
<input type="checkbox" name="kid[]" value="1" <?php if( $_REQUEST["kid"] == "1" ){ print( 'checked' ); } ?>/>
温泉
<input type="checkbox" name="kid[]" value="2" <?php if( $_REQUEST["kid"] == "2" ){ print( 'checked' ); } ?>/>
キャンペーン
<input type="checkbox" name="kid[]" value="3" <?php if( $_REQUEST["kid"] == "3" ){ print( 'checked' ); } ?>/>
イベント
<input type="checkbox" name="kid[]" value="4" <?php if( $_REQUEST["kid"] == "4" ){ print( 'checked' ); } ?>/>
特別室<br />
<input type="checkbox" name="kid[]" value="5" <?php if( $_REQUEST["kid"] == "5" ){ print( 'checked' ); } ?>/>
和室
<input type="checkbox" name="kid[]" value="6" <?php if( $_REQUEST["kid"] == "6" ){ print( 'checked' ); } ?>/>
喫煙室</td>

</tr>
<tr>
<th>価格帯</th>
<td>
<input type="text" name="price_min" value="<?php print( htmlspecialchars( $_REQUEST["price_min"] ,ENT_QUOTES ) ) ?>" size="8"> ~
<input type="text" name="price_max" value="<?php print( htmlspecialchars( $_REQUEST["price_max"] ,ENT_QUOTES ) ) ?>" size="8"><br />
</td>
</tr>
<tr>
<th>住所</th>
<td><input type="text" name="address" value="<?php print( htmlspecialchars( $_REQUEST["address"] ,ENT_QUOTES ) ) ?>" size="20"></td>
</tr>


</table>
<input type="submit" value="検索" class="Btn-gray button">
</form>

<p>&nbsp;</p>

<?php
//初期設定
//username,$password,$dbnameは適当に

if( $_REQUEST["cmd"] == "search" ){


$dsn = 'mysql:host=localhost;dbname=hotel_reservation';
$username = 'root';
$password = 'xxxxxx';
$data=array();

$sql = "SELECT t1.* FROM t_hotels as t1 ";

$flag=true;


//kid絞り込み
if(isset($_REQUEST["kid"]) and is_array($_REQUEST["kid"])){
$sql.="INNER JOIN (SELECT DISTINCT hid FROM t_hotel_kodawari WHERE kid in (";
$sql.=implode(",",array_fill(0,count($_REQUEST["kid"]), '?'));
$sql.=")) as t2 ON t1.id=t2.hid ";
$data=array_merge($data,$_REQUEST["kid"]);
$flag=false;
}

//WHERE句作成
$sql.= "WHERE 1 ";

//住所絞込み
if(isset($_REQUEST["address"]) and $_REQUEST["address"]!==""){
$sql.="AND address LIKE ? ";
array_push($data, "%" .$_REQUEST["address"]."%");
$flag=false;
}

//価格絞り込み
if(isset($_REQUEST["price_min"]) and $_REQUEST["price_min"]!==""){
$price_min=str_replace(",","",$_REQUEST["price_min"]);
}else{
$price_min=0;
}
if(isset($_REQUEST["price_max"]) and $_REQUEST["price_max"]!==""){
$price_max=str_replace(",","",$_REQUEST["price_max"]);
}else{
$price_max=1000000;
}
if(isset($_REQUEST["price_min"]) or isset($_REQUEST["price_max"])){
$sql.="AND price BETWEEN ? AND ? ";
array_push($data,$price_min,$price_max);
$flag=false;
}

//なにもパラメータがないときは表示しない
if($flag) $sql.="AND 0 ";;

//参考
print $sql."<br>";
print_r($data);

//実行
$pdo = new PDO($dsn,$username,$password);
$stmt = $pdo->prepare($sql);
$stmt->execute($data);

while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$rows[]=$row;
};
print_r($rows);

?>

<table border="1">
<caption>検索結果</caption>
<tr>
<th></th>
<th>ホテル名</th>
<th>宿泊料金</th>
<th>住所</th>
</tr>

<?php
foreach( $rows as $row ){
?>
<tr>
<td><img src="hotel/<?php print( htmlspecialchars( $result["id"], ENT_QUOTES )); ?>.png" /></td>
<td><?php print( htmlspecialchars( $result["hotel_name"], ENT_QUOTES )); ?></td>

<td>\<?php print( htmlspecialchars( number_format( $result["price_min"] ),ENT_QUOTES ) ); ?></td>
<td>
<?php print( htmlspecialchars( $result["address"], ENT_QUOTES ) ); ?>


</td>
</tr>
<?php
}
}
?>
</table>
</div>
</body>
</html>
投稿日時 - 2014-06-23 22:24:02
  • ありがとう数0
  • 回答No.4
レベル14

ベストアンサー率 51% (3827/7415)

>Warning: Invalid argument supplied for foreach() in に表示される行番号って foreach( $rows as $row ){ のところですか? $rowsが配列じゃない文字列や数値の時にでるエラーですね とりあえず foreach((array) $rows as $row ){ とすれば、なおるような気もしますが、 なぜここで$rowsが ...続きを読む
>Warning: Invalid argument supplied for foreach() in

に表示される行番号って

foreach( $rows as $row ){
のところですか?

$rowsが配列じゃない文字列や数値の時にでるエラーですね

とりあえず
foreach((array) $rows as $row ){

とすれば、なおるような気もしますが、
なぜここで$rowsが配列でなくなっているのかちょっとわかりません。
なにかタイプミスがあるのでしょうか?
  • ありがとう数0
  • 回答数5
  • 気になる数0
このQ&Aで解決しましたか?

関連するQ&A

-PR-
-PR-
このQ&Aにこう思った!同じようなことあった!感想や体験を書こう
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


-PR-

ピックアップ

-PR-
ページ先頭へ