総当り表を作成するためのPHPコードのサンプルとは?

このQ&Aのポイント
  • 特定のデータを使用して総当り表を作成するためには、PHPを使用することが必要です。
  • 以下のSQL文を使用して、必要なデータを取得することができます。
  • 取得したデータを使って、総当り表を作成するためのPHPコードのサンプルを以下に示します。
回答を見る
  • ベストアンサー

総当り表

以前にご質問させていただきましたが、時間が経ってしまったため、再度ご質問させていただきました。 create table team(team_id int not null primary key,team_name varchar(30),year int(4), leagueid int(32) ); insert into team values (1,"A",2012,1), (2,"B",2012,1), (3,"C",2012,1), (4,"D",2012,1), (5,"A",2012,2), (6,"B",2012,2), (7,"C",2012,2), (8,"D",2012,2), (9,"A",2011,1), (10,"B",2011,1), (11,"C",2011,1), (12,"D",2011,1); create table taisen(id int not null primary key auto_increment,hometeam int,homepoint int,awayteam int,awaypoint int); insert into taisen (hometeam,homepoint,awayteam,awaypoint) values (1,3,2,2), (3,1,4,0), (1,0,3,2), (2,2,4,2), (1,1,4,2), (2,0,3,0), (2,1,1,2), (4,1,3,3), (3,5,1,2), (5,3,6,3), (5,1,7,1), (7,1,8,1), (9,1,10,1), (11,1,12,3); 上記のデータを使用し、下記の参考サイトの戦績表みたいな作成を考えております。 http://match.nadeshikoleague.jp/2013/nadeshiko_cup_a/match/fight.html 参考サイトですと1チームに対し、2試合ずつになっていますが、1試合を考えております。 SQL文で対戦したデータの呼び出しはできていると思います。 SELECT t.team_id, t.year, t.team_name AS hometeamname, t.leagueid, ti.homepoint, ti.awaypoint, t1.team_name AS awayteamname FROM team AS t1 INNER JOIN (team t INNER JOIN taisen ti ON t.team_id = ti.hometeam) ON t1.team_id = ti.awayteam WHERE t.`year` = '2012' AND t.`leagueid` = 1 上記でうけとったデータにて総当り表を作成したいのですが、 PHPでどのように記述したらよろしいでしょうか? サンプルコードなどいただけると幸いです。 また、対戦していないところに関しては「-」というのを入れたいです。 お分かりの方が、いらっしゃいましたらご教授お願いします

  • PHP
  • 回答数6
  • ありがとう数1

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

  • ベストアンサー
noname#244856
noname#244856
回答No.6

チーム名がA,B,C,D,...,Lだと仮定すると、 $teams = range('A', 'L'); $table = array_fill_keys($teams, array_fill_keys($teams, '-')); $sql = 'SELECT ...'; $result = mysql_query($sql, $link); while ($game = mysql_fetch_assoc($result)) {  if ($game['homepoint'] > $game['awaypoint']) {   $table[$game['hometeam']][$game['awayteam']] = $game['homepoint'] . '○' . $game['awaypoint'];   $table[$game['awayteam']][$game['hometeam']] = $game['awaypoint'] . '●' . $game['homepoint'];  } elseif ($game['homepoint'] < $game['awaypoint']) {   $table[$game['hometeam']][$game['awayteam']] = $game['homepoint'] . '●' . $game['awaypoint'];   $table[$game['awayteam']][$game['hometeam']] = $game['awaypoint'] . '○' . $game['homepoint'];  } else {   $table[$game['hometeam']][$game['awayteam']] = $game['homepoint'] . '△' . $game['awaypoint'];   $table[$game['awayteam']][$game['hometeam']] = $game['awaypoint'] . '△' . $game['homepoint'];  } } が正しいです。(全角スペースでインデントしてるので注意) チームIDを取ってくるなら $teams = range(1, 12); チーム名を取ってくるなら $teams = range('A', 'L'); としないといけないのは自明ですよね。 実際にはこんな連番じゃなくてちゃんとした名前になってると思いますが。

h199613
質問者

お礼

実装することができました。 最後までお付き合いいただき、誠に有難う御座います。

その他の回答 (5)

noname#244856
noname#244856
回答No.5

デバッグはE_NOTICE非表示でされているんでしょうか? であるとすればバグを発見するのが非常に難しくなるので今後は表示するようにしましょう。 http://qiita.com/mpyw/items/2f9955db1c02eeef43ea 未定義の変数がNULLに自動的に初期化されて、さらに配列のキーにセットするときに自動的に空文字に変換されて、 $table[""][""] に最後に取得した結果だけ入っているんだと思います。 サンプルデータのように取得するには SELECT t.team_name AS hometeam, ti.homepoint, ti.awaypoint, t1.team_name AS awayteam FROM team AS t1 INNER JOIN (team t INNER JOIN taisen ti ON t.team_id = ti.hometeam) ON t1.team_id = ti.awayteam WHERE t.`year` = '2012' AND t.`leagueid` = 1 が正しいですね。

h199613
質問者

補足

デバックの件了解いたしました。 有難うございます。 上記のSELECT文にてA~Dのデータはとれたのですが、 今度は http://codepad.org/GpkPg1Rz のように表示されてしまいます。 なんどもご質問、お手数をお掛けいたしますが、完成までお付き合いいただければと思っていますので、 宜しくお願いいたします。

noname#244856
noname#244856
回答No.4

うーん、ちゃんとデータがSELECT出来ていないような気がします・・・ while($game = mysql_fetch_assoc($result)) { の直後に var_dump($game); を入れてみてください。 期待する個数より少ない個数しか取得できていなかったり、カラム名が期待しているものと違ったりする場合があるかもしれないので、私が提示したサンプルデータ内で使用されている$gamesの各要素のような形で取得できているか再確認してください。 なお、チーム名を表に入れたい場合はarray_fill_keysの第1引数にチーム名の配列を代わりに入れていただければ実現できます。その場合は取得するデータの「hometeam」と「awayteam」がそれぞれチーム名となるようにしてください。

h199613
質問者

補足

dumpしたところ http://codepad.org/kU0Pgrqc のように返ってきており、ご教授いただいた$gamesとは違った内容になっています。 SELECT文がおかしいということはありますでしょうか? チーム名の件に関しましては了解いたしました。 データがちゃんと取れた場合実装してみます。

noname#244856
noname#244856
回答No.3

while($rows = mysql_fetch_assoc($sql)) { foreach ($rows as $game) { ... } } ではなくて $sql = 'SELECT ...'; $result = mysql_query($sql, $link); while($game = mysql_fetch_assoc($result)) { ... } ですね。 繰り返しますがmysql関数は非推奨なのでPDOへの書き換えをおすすめします。 PDOであれば foreach ($pdo->query('SELECT ...') as $game) { ... } のようにかなりスマートに書けます。 ちなみにこの際使用されるのはPDO::ATTR_DEFAULT_FETCH_MODEで指定したフェッチモードで、 デフォルトはPDO::FETCH_BOTHとなっています。 PDO::FETCH_ASSOCかPDO::FETCH_OBJに変更することを推奨します。 詳しくはこちらで。 http://qiita.com/mpyw/items/b00b72c5c95aac573b71

h199613
質問者

補足

こんがらがってしまったため、再度整理させていただきたいと思っています。 PDOは今回は申し訳ないのですがなしでお願いいたします。(今後勉強させていただきます。) $sql = 'SELECT ...'; $result = mysql_query($sql, $link); while($game = mysql_fetch_assoc($result)) { if ($game['homepoint'] > $game['awaypoint']) { $table[$game['hometeam']][$game['awayteam']] = $game['homepoint'] . '○' . $game['awaypoint']; $table[$game['awayteam']][$game['hometeam']] = $game['awaypoint'] . '●' . $game['homepoint']; } elseif ($game['homepoint'] < $game['awaypoint']) { $table[$game['hometeam']][$game['awayteam']] = $game['homepoint'] . '●' . $game['awaypoint']; $table[$game['awayteam']][$game['hometeam']] = $game['awaypoint'] . '○' . $game['homepoint']; } else { $table[$game['hometeam']][$game['awayteam']] = $game['homepoint'] . '△' . $game['awaypoint']; $table[$game['awayteam']][$game['hometeam']] = $game['awaypoint'] . '△' . $game['homepoint']; } } にてデータを取得した後に foreach($teams as $team) { $name .= '<th class="top">' .$team. '</th>'."\n"; } と foreach($table as $team => $line) { $list .= '<tr>'."\n"; $list .= '<th>' .$team. '</th>'."\n"; foreach ($line as $cell) { $list .= '<td>' .$cell. '</td>'."\n"; } $list .= '</tr>'."\n"; } としており、 html側にて吐き出したところ <table> <thead> <tr> <th class="first"></th> <?php echo $teamName; ?> </tr> </thead> <tbody> <?php echo $leagueList; ?> </tbody> </table>   1 2 3 4 5 6 7 8 9 10 11 12 1 - - - - - - - - - - - - 2 - - - - - - - - - - - - 3 - - - - - - - - - - - - 4 - - - - - - - - - - - - 5 - - - - - - - - - - - - 6 - - - - - - - - - - - - 7 - - - - - - - - - - - - 8 - - - - - - - - - - - - 9 - - - - - - - - - - - - 10 - - - - - - - - - - - - 11 - - - - - - - - - - - - 12 - - - - - - - - - - - -   2●5 と表示されてしまいます。 原因がわかりますでしょうか。 また、現在縦、横に1~12の番号が振られてるかと思いますが、こちらをチーム名にすることも可能でしょうか?

noname#244856
noname#244856
回答No.2

こんな感じ? http://codepad.org/vln3p4Dr http://codepad.viper-7.com/Lx33Ts CSSでカッコ良くしてみました。

h199613
質問者

補足

有難う御座います。 実装させていただいてるのでが、うまくいかず困っています。 http://codepad.org/Myfu9zBA としており、それをforeachでまわしているのですが、結果が 1 2 3 4 5 6 7 8 9 10 11 12 1 1△1 - - - - - - - - - - - 2 - 2△2 - - - - - - - - - - 3 - - 3△3 - - - - - - - - - 4 - - - 4△4 - - - - - - - - 5 - - - - 5△5 - - - - - - - 6 - - - - - - - - - - - - 7 - - - - - - - - - - - - 8 - - - - - - - - - - - - 9 - - - - - - - - - - - - 10 - - - - - - - - - - - - 11 - - - - - - - - - - - - 12 - - - - - - - - - - - - A A△A B B△B C C△C 0 0△0 D D△D といった内容になってしまいます。

noname#244856
noname#244856
回答No.1

データベースの扱いに関して http://qiita.com/mpyw/items/b00b72c5c95aac573b71 総当たり表の作り方 http://codepad.org/zWREtyF3

h199613
質問者

補足

ご解答有難う御座います。 また、サンプルのご提供も誠に有難う御座います。 総当たり表の作り方まではできたのですが、ここから表に作っていくにはどうしたらよろしいでしょうか。 度重なるご質問で申し訳ありませんが、宜しくお願いいたします。

関連するQ&A

  • tableの連結

    http://okwave.jp/qa/q7944235.html の件に引き続きどうSQL文を書いてよいかわからず困っています。 create table team(team_id int not null primary key,team_name varchar(30),year int(4), leagueid int(32) ); insert into team values(1,"A",2012,1),(2,"B",2012,1),(3,"C",2012,1),(4,"D",2012,1),(5,"A",2012,2),(6,"B",2012,2),(7,"C",2012,2),(8,"D",2012,2),(9,"A",2011,1),(10,"B",2011,1),(11,"C",2011,1),(12,"D",2011,1); create table taisen(id int not null primary key auto_increment,hometeam int,homepoint int,awayteam int,awaypoint int); insert into taisen (hometeam,homepoint,awayteam,awaypoint) values(1,3,2,2),(3,1,4,0),(1,0,3,2),(2,2,4,2),(1,1,4,2),(2,0,3,0),(2,1,1,2),(4,1,3,3),(3,5,1,2),(5,3,6,3),(5,1,7,1),(7,1,8,1),(9,1,10,1),(11,1,12,3); とあり、 taisen.hometeamとteam.idとtaisen.awayteamとteam.idを結合し、taisenテーブルにteamのyear、leagueid、team_nameが表示されればと思っています。 通常のjoinであればできるのですが、どのようにsql文をかけばよいのかわからず困っています。 taisen.hometeamとteam.idとtaisen.awayteamとteam.idを結合したときに | taisen.hometeam | ホームチーム名 | taisen.homepoint | taisen.awayteam | アウェイチーム名 | taisen.awaypoint | team.year | team.leagueid で結果がとれるようにしたいのですが、どのようにしたらよろしいでしょうか?

    • ベストアンサー
    • MySQL
  • SQL文にて順位表をつくりたい

    create table team(team_id int not null primary key,team_name varchar(30),year int(4), leagueid int(32) ); insert into team values(1,"A",2012,1),(2,"B",2012,1),(3,"C",2012,1),(4,"D",2012,1),(5,"A",2012,2),(6,"B",2012,2),(7,"C",2012,2),(8,"D",2012,2),(9,"A",2011,1),(10,"B",2011,1),(11,"C",2011,1),(12,"D",2011,1); create table taisen(id int not null primary key auto_increment,hometeam int,homepoint int,awayteam int,awaypoint int); insert into taisen (hometeam,homepoint,awayteam,awaypoint) values(1,3,2,2),(3,1,4,0),(1,0,3,2),(2,2,4,2),(1,1,4,2),(2,0,3,0),(2,1,1,2),(4,1,3,3),(3,5,1,2),(5,3,6,3),(5,1,7,1),(7,1,8,1),(9,1,10,1),(11,1,12,3); データベース内にデータがあったときに年やleague_idごとに順位表を作りたいのですが、どのようにSQL文を書いてよいかわからず困っています。 理想はこのような感じです。 http://soccer.yahoo.co.jp/ws/standing/?l=52 お分かりの方がいらっしゃいましたらご教授お願いいたします。

    • ベストアンサー
    • MySQL
  • どなたか教えてください。

    どなたかお分かりの方がいらっしゃいましたらご教授お願いします。 本当に困っております。 create table team(team_id int not null primary key,team_name varchar(30),year int(4), leagueid int(32) ); insert into team values(1,"A",2012,1),(2,"B",2012,1),(3,"C",2012,1),(4,"D",2012,1),(5,"A",2012,2),(6,"B",2012,2),(7,"C",2012,2),(8,"D",2012,2),(9,"A",2011,1),(10,"B",2011,1),(11,"C",2011,1),(12,"D",2011,1); create table taisen(id int not null primary key auto_increment,hometeam int,homepoint int,awayteam int,awaypoint int); insert into taisen (hometeam,homepoint,awayteam,awaypoint) values(1,3,2,2),(3,1,4,0),(1,0,3,2),(2,2,4,2),(1,1,4,2),(2,0,3,0),(2,1,1,2),(4,1,3,3),(3,5,1,2),(5,3,6,3),(5,1,7,1),(7,1,8,1),(9,1,10,1),(11,1,12,3); select (select count(*)+1 from ( select team_id ,sum((homepoint>awaypoint)*3 +(homepoint=awaypoint)) as 勝ち点 ,sum(homepoint) - sum(awaypoint) as 得失点差 ,sum(homepoint) as 得点 from ( select hometeam as team_id,homepoint,awaypoint from taisen union all select awayteam as team,awaypoint,homepoint from taisen ) as sub1 group by team_id ) as sub2 where 勝ち点>(@a:=coalesce(sum((homepoint>awaypoint)*3 +(homepoint=awaypoint)),0)) or ( 勝ち点=@a and 得失点差>@b:=coalesce((sum(homepoint) - sum(awaypoint)),0)) or ( 勝ち点=@a and 得失点差=@b and 得点>coalesce(sum(homepoint),0)) ) as 順位 ,year 年度 ,leagueid リーグID ,team_name チーム名 ,coalesce(sum((homepoint>awaypoint)*3 +(homepoint=awaypoint)),0) as 勝ち点 ,coalesce(count(sub.team_id),0) as 試合数 ,coalesce(sum(homepoint>awaypoint),0) as 勝ち数 ,coalesce(sum(homepoint=awaypoint),0) as 引き分け ,coalesce(sum(homepoint<awaypoint),0) as 負け数 ,coalesce(sum(homepoint),0) as 得点 ,coalesce(sum(awaypoint),0) as 失点 ,coalesce(sum(homepoint) - sum(awaypoint),0) as 得失点差 from ( select hometeam as team_id,homepoint,awaypoint from taisen union all select awayteam as team,awaypoint,homepoint from taisen ) as sub right join team on sub.team_id=team.team_id where team.year = 2012 and team.leagueid = 2 group by team.team_id order by 勝ち点 desc, 得失点差 desc, team.team_id asc; とした場合、順位が5位からの表示になってしまいます。 これを1位からの表示にしたいのですが、どのように変更したらよいのかわからず困っており、whereのteam.yearとteam.league.idを変更するたびに順位をリセット(?)する方法を知りたいです。 お分かりの方がいらっしゃいましたらご教授お願いします。

    • 締切済み
    • PHP
  • PHPとMysqlを使用した集計表の作り方

    --------------媒体-------------- CREATE TABLE IF NOT EXISTS `media` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; INSERT INTO `media` (`id`, `name`) VALUES (1, 'yahoo'), (2, '楽天'), (3, '電話'), (4, 'メール'), (5, 'その他'); --------------店舗-------------- CREATE TABLE IF NOT EXISTS `shop` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; INSERT INTO `shop` (`id`, `name`) VALUES (1, '新宿'), (2, '池袋'), (3, '渋谷'), (4, '博多'), (5, '梅田'); --------------来客数-------------- CREATE TABLE IF NOT EXISTS `raikyakusuu` ( `id` int(11) NOT NULL AUTO_INCREMENT, `date` date DEFAULT NULL, `shop_id` int(2) DEFAULT NULL, `media_id` int(2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; INSERT INTO `raikyakusuu` (`id`, `date`, `shop_id`, `media_id`) VALUES (1, '2013-11-01', 1, 1), (2, '2013-11-01', 1, 1), (3, '2013-11-01', 1, 2), (4, '2013-11-01', 4, 4), (5, '2013-11-01', 1, 2), (6, '2013-11-02', 3, 1), (8, '2013-11-02', 3, 4), (9, '2013-11-02', 2, 2), (10, '2013-11-02', 2, 4), (11, '2013-11-03', 1, 4), (12, '2013-11-03', 3, 1), (13, '2013-11-05', 4, 3), (14, '2013-11-05', 1, 3), (15, '2013-11-06', 2, 2), (16, '2013-11-06', 3, 3), (17, '2013-11-06', 1, 5); select DATE_FORMAT(r.`date`,'%d日') as DayTime, count(*) as cnt, s.`name` as s_name, m.`name` as m_name from raikyakusuu r LEFT JOIN shop s ON s.`id` = r.`shop_id` LEFT JOIN media m ON m.`id` = r.`media_id` WHERE DATE_FORMAT(r.`date`, '%Y-%m') = '2013-11' GROUP BY DayTime, m.`name` 上記のセレクト文で取れた結果をPHPにて 新宿 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 楽天 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | メール | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 池袋 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 楽天 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | メール | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 渋谷 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 楽天 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | メール | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | といったようにtableにて表示を考えておりますが、 うまくだせずに困っております。 条件といたしましては、 結果で取れていない媒体、日付も表示させ、cntには0と表示させたいです。 お分かりの方がいらっしゃいましたらご教示お願いいたします。 端折らせていただいている部分も御座いますが、宜しくお願いいたします。

    • ベストアンサー
    • PHP
  • 表の結合と並べ替え

    次のようなテーブル構成で、 CREATE TABLE tbl1 ( id int PRIMARY KEY AUTO_INCREMENT ) ENGINE=InnoDB; CREATE TABLE tbl2 ( id int PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) ) ENGINE=InnoDB; CREATE TABLE tbl1_tbl2 ( id int PRIMARY KEY AUTO_INCREMENT, tbl1_id int, tbl2_id int, FOREIGN KEY(tbl1_id) REFERENCES tbl1(id), FOREIGN KEY(tbl2_id) REFERENCES tbl2(id) ) ENGINE=InnoDB; CREATE TABLE tbl3 ( id INT PRIMARY KEY AUTO_INCREMENT, tbl1_id int, created datetime, FOREIGN KEY(tbl1_id) REFERENCES tbl1(id) ) ENGINE=InnoDB; [tbl1] id 1 2 3 [tbl2] id  name 1   a 2   b [tbl1_tbl2] id  tbl1_id  tbl2_id 1   1      1 2   1      2 3   1      2 4   2      1 5   3      1 6   3      2 [tbl3] id  tbl1_id  created 1   1    2011-10-17 01:51:39 2   1    2011-10-17 02:51:39 3   3    2000-10-17 01:51:39 ここから次のような「tbl1のid」「tbl2の個数」「tbl3の最新のcreated」を基準とした (下の例は「tbl1のid」を昇順にした結果です) それぞれの並べ替た結果を得たいのですが、どのようなSQL文を記述すれば良いのでしょうか? [tbl1のid] [tbl2のnameのリスト] [tbl3の最新のcreated]   1         a,b,b      2011-10-17 02:51:39   2         a           3         a,b       2000-10-17 01:51:39

    • ベストアンサー
    • MySQL
  • MySQL SELECTの指定について

    まず、御覧頂きありがとうございます。 早速質問なのですが、 CREATE TABLE `hoge` ( `id` int(8) NOT NULL, `name` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `hoge` (`id`, `name`) VALUES (1, 'hogeA'), (2, 'hogeB'), (3, 'hogeC'), (4, 'hogeD'); CREATE TABLE `test` ( `id` int(8) NOT NULL, `name` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `test` (`id`, `name`) VALUES (1, 'testA'), (4, 'testD'); という値が入ってるテーブルがあるとします。(長くなってすみません) で、 hoge.id と test.id が重複した場合 test.name を表示させたいです。 期待値としては id,name 1.testA 2,hogeB 3,hogeC 4,testD になります。 業務でJoinを使うようなテーブル構造にそもそもしないというのもあり、クリティカルなSQLコードに不慣れで御知恵を借りたく質問させて頂きました。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 指定された趣味を持つメンバーがいるグループを抽出するSQL

    グループテーブル、メンバーテーブル、趣味テーブルの3つのテーブルがあります。 あるメンバーはあるグループに属しており、趣味を1つ持っています。 以下がそのSQLです。 CREATE TABLE groups ( g_id int primary key ); CREATE TABLE members ( m_id int primary key , g_id int , h_id int ); CREATE TABLE hobbies ( h_id int primary key, h_name text ); INSERT INTO groups VALUES ( 1 ); INSERT INTO groups VALUES ( 2 ); INSERT INTO groups VALUES ( 3 ); INSERT INTO members VALUES ( 1, 1, 1); INSERT INTO members VALUES ( 2, 1, 3); INSERT INTO members VALUES ( 3, 1, 4); INSERT INTO members VALUES ( 4, 1, 4); INSERT INTO members VALUES ( 5, 2, 1); INSERT INTO members VALUES ( 6, 2, 2); INSERT INTO members VALUES ( 7, 2, 3); INSERT INTO members VALUES ( 8, 3, 2); INSERT INTO members VALUES ( 9, 3, 3); INSERT INTO members VALUES ( 10, 3, 4); INSERT INTO hobbies VALUES ( 1, 'sports' ); INSERT INTO hobbies VALUES ( 2, 'music' ); INSERT INTO hobbies VALUES ( 3, 'book' ); INSERT INTO hobbies VALUES ( 4, 'drive' ); 指定された趣味を持つメンバーがいるグループを抽出するにはどうすればいいでしょうか? 例えば、「読書が趣味なメンバーとドライブが趣味なメンバーがいるグループは?」「グループ1とグループ3」のような感じです。 一応自分で考えてみたのが、以下ですが、これだと趣味の指定が増減すると大きくSQLが変わってしまいます。 もっといいやり方はないでしょうか? 私はPostgreSQL8を使ってますが、汎用的なSQLであれば、そっちの方がいいです。 SELECT distinct m.g_id FROM members m join hobbies h ON m.h_id = h.h_id where h.h_name = 'drive' INTERSECT SELECT distinct m.g_id FROM members m join hobbies h ON m.h_id = h.h_id where h.h_name = 'book';

  • 結合?の仕方がわからず困っています。

    こんにちは、ほぼ初心者ですがよろしくお願いします。 sqlite2 で以下のような倉庫テーブルと在庫数テーブルがあったとして、 手順5で、ある品物(item_id = 1)の倉庫ごとの在庫数を取得したいと思っています。 倉庫に結合する在庫データがなくても、 倉庫に対する行を取得できる SQL 文を教えていただけませんでしょうか? ※そもそもテーブルの作り方がおかしいでしょうか? その辺も含めてアドバイスいただけるとありがたいです。 -- 以下sqlite です .mode column .header ON -- 手順1 倉庫テーブル CREATE TABLE stock_sites ( id INTEGER NOT NULL PRIMARY KEY , name TEXT NOT NULL ); -- 手順2 在庫テーブル CREATE TABLE stocks ( id INTEGER NOT NULL PRIMARY KEY , stock_site_id INTEGER NOT NULL, item_id INTEGER NOT NULL, stock INTEGER NOT NULL, UNIQUE(stock_site_id, item_id) ); -- 手順3、倉庫データ INSERT INTO stock_sites(name) VALUES('site_A'); INSERT INTO stock_sites(name) VALUES('site_B'); INSERT INTO stock_sites(name) VALUES('site_C'); -- 手順4、在庫データ INSERT INTO stocks(stock_site_id, item_id, stock) VALUES(1,1,10); INSERT INTO stocks(stock_site_id, item_id, stock) VALUES(2,2,20); -- 手順5 ある品の倉庫ごとの在庫数を取得したい SELECT t1.name AS site_name, t2.* FROM stock_sites AS t1 LEFT JOIN stocks AS t2 ON t1.id = t2.stock_site_id WHERE t2.item_id = 1 ORDER BY t1.id; -- 結果 -- site_name  t2.id   t2.stock_site_id t2.item_id t2.stock -- ---------- ---------- ---------------- ---------- ---------- -- site_A   1      1         1     10 -- 欲しい結果 -- site_name  t2.id   t2.stock_site_id t2.item_id t2.stock -- ---------- ---------- ---------------- ---------- ---------- -- site_A   1      1         1     10 -- site_B -- site_C

  • UPDATE文のエラー直せますでしょうか?

    テーブル A と テーブル B は同じ構造です。 A のレコードを B のレコードで更新するにはどうすれば良いのでしょうか? UPDATE a Set( a.id = b.id, a.dat = b.dat ) FROM a INNER JOIN b ON a.id = b.id #1064 - You have an error in your SQL syntax; the right syntax to use near '( a.id = b.id, a.d = b.d ) FROM a INNER JOIN b ON a.id = b.id' at line 1 MySQL 5.1.33 CREATE TABLE `a` ( `id` INT NOT NULL , `dat` INT , PRIMARY KEY ( `id` ) );

    • ベストアンサー
    • MySQL
  • 複数JOINしているとCOUNTが正しく取得できな

    LAMP環境で開発をしています。 SQL文でCOUNTを求める際に、まとめて結果を求めようとして上手く行きません。 状況としては以下です。 テーブルdはidをkeyにa,b,c3つのテーブルとjoinしています。 id = 1の場合、テーブルa,b,cにマッチするレコードがそれぞれに4個、1個、0個あります。 ひとつひとつを SELECT COUNT(CASE WHEN a.name IS null THEN 1 ELSE null END) as a_count FROM d INNER JOIN a ON a.id = d.id WHERE d.id = 1 として結果を求めると4,1,0と出るのですが、まとめて SELECT COUNT(CASE WHEN a.name IS null THEN 1 ELSE null END) as a_count, COUNT(CASE WHEN b.name IS null THEN 1 ELSE null END) as b_count, COUNT(CASE WHEN c.name IS null THEN 1 ELSE null END) as c_count FROM d INNER JOIN a ON a.id = d.id INNER JOIN b ON b.id = d.id INNER JOIN c ON c.id = d.id WHERE d.id = 1 とすると28,5,0という値が返されます。 どのように書けば正しい4,1,0を得られるのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL

専門家に質問してみよう