みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

SQLの効率化について

下記のようなテーブルがあり、idの値を渡すと、下記のレコードを取得したいと思います。
1. 渡されたid=idのレコード
2. 渡されたid=parent_idのレコード
3. 渡されたid=parent_idのid=parent_idのレコード

【テーブル】
CREATE TABLE IF NOT EXISTS `tbl` (
`id` varchar(4) NOT NULL,
`name` varchar(100) NOT NULL,
`parent_id` varchar(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `tbl` (`id`, `name`, `parent_id`) VALUES
('0001', '親1', '0'),
('0002', '親2', '0'),
('0011', '子1-1', '0001'),
('0012', '子1-2', '0001'),
('0021', '子2-1', '0002'),
('0022', '子2-2', '0002'),
('0101', '子1-1-1', '0011'),
('0102', '子1-1-2', '0011'),
('0103', '子1-1-3', '0011'),
('0121', '子2-1-1', '0021');

下記はそのソースとなり、やりたい事は出来ているのですが、SQLを3回実行しています。

多分2回目の$idに1回目の結果の$row["id"]、3回目の$id[$cnt]に2回目の結果の$s_idをセットすることが出来れば、1回のsql文で記述できるのではと思いましたが、
どのようなSQL文を書けば良いか分からなかった為、アドバイスいただける方がいらっしゃいましたら、ご教示の程よろしくお願いします。

【ソース】
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>title</title>
</head>
<body>
<?php
$link = mysql_connect('MySQL サーバ','ユーザー名','パスワード');
if (!$link) {
die('接続できませんでした:' . mysql_error());
}

if (!mysql_select_db('データベース名', $link)) {
die ('データベースの選択失敗');
}

$hairetsu = array();
$f_id = array();
$f_name = array();
$f_parent_id = array();
$s_id = array();
$s_name = array();
$s_parent_id = array();
$t_id = array();
$t_name = array();
$t_parent_id = array();

// 1回目
$query = mysql_query("SELECT * FROM tbl where id = '0001'", $link);
if (!$query) {
die(mysql_error());
}

$row = mysql_fetch_array($query);

$hairetsu["f_id"] = $row["id"];
$hairetsu["f_name"] = $row["name"];
$hairetsu["f_parent_id"] = $row["parent_id"];

$id = $row["id"];
// 2回目
$query = mysql_query("SELECT * FROM tbl where parent_id = $id", $link);
if (!$query) {
die(mysql_error());
}

while ($row = mysql_fetch_array($query)) {
array_push($s_id, $row["id"]);
array_push($s_name, $row["name"]);
array_push($s_parent_id, $row["parent_id"]);
}

$hairetsu["s_id"] = $s_id;
$hairetsu["s_name"] = $s_name;
$hairetsu["s_parent_id"] = $s_parent_id;

$id = $hairetsu["s_id"];
// 3回目
for($cnt=0; $cnt<count($id); $cnt++) {
$query = mysql_query("SELECT * FROM tbl where parent_id = $id[$cnt]", $link);
if (!$query) {
die(mysql_error());
}
while ($row = mysql_fetch_array($query)) {
array_push($t_id, $row["id"]);
array_push($t_name, $row["name"]);
array_push($t_parent_id, $row["parent_id"]);
}
}

$hairetsu["t_id"] = $t_id;
$hairetsu["t_name"] = $t_name;
$hairetsu["t_parent_id"] = $t_parent_id;

echo "<pre>";
var_dump($hairetsu);
echo "</pre>";

mysql_close($link);
?>
</body>
</html>

以上、宜しくお願いします。

投稿日時 - 2011-07-03 14:40:29

QNo.6851365

すぐに回答ほしいです

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

SQLの発行回数を減らすということであれば下記のようなSQLで1度に結果取得できると思います。
iroha_168さんのサンプルプログラムをSQLで表現した感じです。


SELECT * FROM tbl
WHERE id = '0001'
OR parent_id = '0001'
OR parent_id IN (SELECT id FROM tbl WHERE parent_id = '0001')

投稿日時 - 2011-07-03 22:23:37

お礼

ご回答ありがとうございます。
ご教示いただいたSQL文で意図した動作となりました。

このたびはどうもありがとうございました。
以上、よろしくお願いします。

投稿日時 - 2011-07-03 23:22:49

ANo.1

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

こんな感じでしょうか?
select `id`, `name`, `parent_id`
from `tbl`
where `id` = '0001' or `parent_id` = '0001'
union all
select `id`, `name`, `parent_id`
from `tbl`
where `parent_id` in ( select `id` from `tbl` where `parent_id` = '0001' );

最近のOracleやPostgreSQL、SQL Serverでは
with t as ( select id, name, parent_id from tbl where parent_id = '0001' )
select id, name, parent_id
from tbl
where id = '0001'
union all
select id, name, parent_id from t
union all
select id, name, parent_id
from tbl
where parent_id in ( select id from t )

とも書けますが。

投稿日時 - 2011-07-03 22:35:29

お礼

ご回答ありがとうございます。
ご教示いただいた1つ目のSQL文で意図した動作となりました。

また、OracleやPostgreSQL、SQL Serverでの記述方法もご教示いただきありがとうございます。
それらのデータベースを使用する際は参考にさせていただきたいと思います。

このたびはどうもありがとうございました。
以上、よろしくお願いします。

投稿日時 - 2011-07-03 23:24:22