グループ化したSQLの書き方について

このQ&Aのポイント
  • グループ化したSQLを使用して最高得点を取得する方法を教えてください。
  • resultテーブルにはid、stpass、tokuten、branch、dateというフィールドがあります。
  • 最高得点以外のフィールド(branch、date)も表示するSQLの書き方を知りたいです。
回答を見る
  • ベストアンサー

グループ化したSQLの書き方について

id,stpass,tokuten,branch,dateというフィールドをもつresultというテーブルを作成しました。 最高得点(フィールド名:tokuten)は、下記SQL(クエリーで作りました)でできます。 SELECT result.id, result.stpass, Max(result.tokuten) AS tokutenの最大 FROM result GROUP BY result.id, result.stpass; ただ、最高得点(Max(result.tokuten) AS tokutenの最大)を出したと同じレコードのそれ以外のフィールド(branch,date) を表示させるSQL(クエリー)がわかりません。 何方か、ご存知の方おられましたら、ご教授ください。

  • idek
  • お礼率47% (170/361)

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

  • ベストアンサー
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.3

2つ以上の項目を出すならば、2つ目の構文(JOIN構文)を使わないと厳しいです。 少し長くなりますが、自己最高得点を2回以上マークすることもあると思うので、その場合は最新の日付を出しています。 select s.branchname,r.date,s.stuname,r.maxpercent from m_student s left outer join (select r1.stuid,max(r1.date) date,r1.percent maxpercent from result r1 where r1.percent in (select max(r2.percent) from result r2 where r2.stuid=r1.stuid) group by r1.stuid,r1.percent) r on r.stuid=s.stuid 標準構文とは言え、MySQLは手元にないので、別のDBMSでしか稼働確認していません。もし通らないようなら、MySQLカテゴリで識者を探す方が効率がいいかもしれません。 (経験上の得手不得手というのはありますので)

idek
質問者

お礼

これで動きました。 何から何までご指導いただき 大変ありがとうございました。 深く感謝いたします。

その他の回答 (2)

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

>SQL文はどの言語でも同じだと聞いています。 シンプルなSQL文についてはそのとおりです。しかし、実際のDBMSがすべてSQL標準に則った構文をサポートしているかというと、そうではありません。また、バージョンによってもサポート状況は変わります。 (MySQLとかは特にそうです) ご質問の件については、2つ例をあげます。 1) select s.stuname, (select max(tokuten) from result where id=s.stuid) maxtokuten from m_student s 2) select s.stuname,r.maxtokuten from m_student s left outer join (select id, max(tokuten) maxtokuten group by id) r on r.id=s.stuid stpassのフィールドの意味がわからないので、とりあえずm_studentのstuidとresultのidをJOINさせる前提で書いていますが、書き方のポイントはおわかりいただけるのではと思います。

idek
質問者

お礼

ありがとうございました。 $sql="select s.branchname,s.stuname,(select max(percent) from result where stuid=s.stuid) maxpercent from m_student s"; で通りました。 教えていただいたtokutenは、実際はpercentです。わかりやすくする為に書きました。

idek
質問者

補足

$sql="select s.branchname,s.stuname,(select max(percent) from result where stuid=s.stuid) maxpercent from m_student s"; では通るのですが、 $sql="select s.branchname,s.date,s.stuname,(select max(percent) from result where stuid=s.stuid) maxpercent from m_student s"; では、通りません。 エラーメッセージは Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in *** です。 テーブルのフィールドは result:id,cate_a_code,cate_b_code,course,stuid,stpass,date,percent,judgment,branch,branchname,stuname,stuyomi m_student:id,bankcode,stuid,stpass,stuname,stuyomi,d_from,d_to,branchname です。 resultテーブルの該当レコード(最高得点)のdateを表示させるSQLがわかりません。 初心者ですいません。

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.1

何のDBをお使いですか? 以下が動けば、目的は達すると思いますが。。 select * from result r where tokuten in (select max(tokuten) from result where id=r.id and stpass=r.stpass)

idek
質問者

お礼

ACCESS上で確かに動きました。ありがとうございました。

idek
質問者

補足

DBはMySQL5です。(言語PHP5) お教えいただいたSQLで動きました。 SQL文はどの言語でも同じだと聞いています。 以下はご存知の言語を基にしたお答えで結構です。 基本を教えていただいた所で、以下の事をやろうとしたのですが、 できません。 resultテーブルは、試験結果で、試験を受けた人の結果だけが入っています。 試験を受けていない人もいます。 全員(テーブル:m_student)の一覧と試験を受けた人を出したいのですが。 A氏:未受験 B氏:95点(何回か受けたうちの最高得点) C氏:60点(何回か受けたうちの最高得点) D氏:未受験 のように表示したいのですが。 テーブル:m_studentには、id,stuid(ID),stuname(氏名)のフィールドがあります。 1.left joinでresultテーブルとm_studentテーブルを結合 2.tokutenフィールドがある人は、その人の最高点を表示 3.tokutenフィールドがない人(m_studentにしか存在しない)は名前だけ表示 というSQLを書きたいのですが、思いつきません。 私は、ACCESS&VBAはある程度かじっていますが、ダイレクトにSQLを書くのは、 業務上では初めてです。(勉強は少ししたつもりですが) 説明が足りないかもしれません。 また、突拍子もない質問かもしれません。 恐れいります。よろしくお願いします。

関連するQ&A

  • グループ化したSQLの書き方について

    XP&MySQL5&PHP5 ID,PASSWORD,name,tokutenn,zyukennbi,syozoku,bangou というフィールド(すべてテキスト型)を持つテーブル(result)があります。 (ID,PASSWORD,名前、得点、受験日、所属、社員番号) 全個人が最高得点を記録したレコードだけはSQLで書けます。 select ID, name ,max(result.tokuten) as maxtokuten from result group by ID, name ただ、最高得点を出したと同じレコードのそれ以外のフィールド(zyukennbi,syozoku,bangou) を表示させるSQLがわかりません。 何方か、ご存知の方おられましたら、ご教授ください。 よろしくお願いいたします。

    • 締切済み
    • PHP
  • グループ中で最大値を含む行を抽出するSQLはどう書けば良いでしょうか

    列A,Bでグループ化し、グループ中で列Cが最大値の列を取得したいのです。 数百万件あるので極力低コストにしたく、 副問合せはINDEXが効かないと聞いたのですが、 それ以外思いつきませんでした。 副問合せしない方法はないでしょうか? また、副問合せの中でコストの低いSQLはどんなものでしょうか。 ■テーブルです 名前 型 CUST_ID CHAR(8) BRANCH_ID CHAR(4) VALID_DATE DATE MYDATA VARCHAR2(20) CUST_ID BRAN VALID_DA MYDATA 19740704 0000 06-01-01 comment0001 19740704 0000 05-12-01 comment0000 19740704 0000 06-02-01 comment0002 19740704 0001 06-01-01 comment0011 19740704 0001 06-03-01 comment0012 ■このような結果が欲しいのですが。。。 CUST_ID BRAN VALID_DA MYDATA 19740704 0000 06-02-01 comment0002 19740704 0001 06-03-01 comment0012 ■考えたSQLです(検証済) select a.cust_id,a.branch_id,a.valid_date,a.mydata from test a,(select cust_id,branch_id,max(valid_date) as mvd from test group by cust_id,branch_id) b where a.cust_id=b.cust_id and a.branch_id=b.branch_id and a.valid_date=b.mvd ; select a.cust_id,a.branch_id,a.valid_date,a.mydata from test a where not exists (select * from test b where a.cust_id=b.cust_id and a.branch_id < b.branch_id) ; select cust_id,branch_id,valid_date,mydata from test where (cust_id,branch_id,valid_date) in (select cust_id,branch_id,max(valid_date) from test group by cust_id,branch_id) ; select cust_id,branch_id,valid_date,mydata from (select cust_id,branch_id,valid_date,mydata,max(valid_date) over(partition by cust_id,branch_id) as mvd from test) where valid_date=mvd ;

  • SQL文作成のお願い

    前提として下記のようなテーブルがあります。 テーブル名:test フィールド: 1)id: varchar, not null 2)name: varchar 3)date: timestamp with time zone, not null このテーブルに下記のようなレコードがあります。 '00001', 'A', '2005-01-01 00:00:00' '00001', 'B', '2005-07-01 00:00:00' '00001', 'C', '2005-11-01 00:00:00' '00002', 'X', '2005-01-20 00:00:00' '00002', 'Y', '2005-07-20 00:00:00' '00002', 'Z', '2005-11-20 00:00:00' ■今やりたいこと このテーブルからidごとにdateフィールド値が最近のレコードを取得したい。 ■やってみたこと 下記SQLを発行しました。 >select id, max(date) from test group by id order by id 結果==> 00001 2005-11-01 00:00:00 00002 2005-11-20 00:00:00 実際はnameフィールドの値も取得したいのですが、group by句を使うとフィールド指定ができませんでした。 ■だめだったSQL select id, name, max(date) from test group by id order by id どのようにSQLを書けばよろしいでしょうか?

  • あるIDごとの最高値のレコード抽出について

    下記のようなテーブルがあるとします。 それぞれの人の最高得点であるレコードを抽出したいのですが可能でしょうか。 テーブル:result no id point date -------------------- 1 A 60 ... 2 A 70 3 B 50 4 B 90 期待出力 no id point date ------------------- 2 A 70 ... 4 B 90 自分でも色々考えたつもりですが、例えば select max(point) from result group by id; とすると 70,90 という値は抽出されますが、該当レコードの全カラムを出力させたいです。 もし同じidで同じpointのレコードがあった場合は、dateの新しいほうを優先したいです。 id,point,dateがまったく同じレコードは存在しないと仮定します。 この他にもdistinct等も考えましたが、指定したカラムが重複した場合どのレコードが選択されるかは 不定のようですので使えそうにありません。 そもそもSQLだけでこのような出力が可能かどうかもわかりません…。 テーブルの設計が悪いというのもあるのでしょうか。 どなたかご助言くだされば幸いです。

  • SQL文のINNER JOIN内での条件付けについて質問です

    SQLの質問です。 先程も質問させて頂いた件(http://okwave.jp/qa4089307.html)に派生した問題なのですが、 Accessのクエリにて SELECT A.*FROM grade_points AS A INNER JOIN [SELECT MAX(enforcement_date) AS MaxDate,grade_id FROM grade_points WHERE (enforcement_date)<=date() GROUP BY grade_id]. AS B ON (A.grade_id = B.grade_id) AND (A.enforcement_date = B.MaxDate); (前回の件のクエリにWHERE (enforcement_date)<=date() の条件を追加しました) というクエリを作ると、SQLを書いた直後の保存前はちゃんと動くのですが、保存後に閉じてから実行しようとすると「入力テーブルまたはクエリ(上記[]内SQL文)が見つかりません」というエラーになってしまいます。 INNER JOIN内のSQLにWhere条件は使えないのでしょうか??保存前は動くので不思議でなりません… お手数ですがどなたかご意見よろしくお願い致します。

  • SQLのパラメータ・・

    たびたびお世話になっております。 顧客マスタの新規コードを、最大値に1を足して生成しています。 既存の顧客コードの最大値を求める為、 Dim mySQL as Stirng,Rst as Recordset mySQL="SELECT Max(局コード) AS 局コードの最大, 会社コード FROM 顧客マスタ GROUP BY 会社コード HAVING (会社コード=[Forms]![フォーム]![テキスト1]);" Set Rst = CurrentDB.OpenRecordset(mySQL) というSQL文をかきました。 ところが、SQLをレコードセットにすると「パラメータが少なすぎます。1を指定してください(3061)」というエラーメッセージが出てしまいます。 クエリーを作成して実行しても正しい結果を返すのに、SQLだとダメなのはなぜなのでしょうか。 どうぞよろしくお願いいたします。

  • SQL GROUP BY

    SQLについてお聞きしたいです。番号カラムの中で最大の数字をもつフィールドと 同じコードを持つデータを、表から全て取得したいと思っているのですが 書き出すとGROUP BYの式が間違っているというエラーが出てしまいます。 SELECT * FROM 表 GROUP BY コード HAVING MAX(番号) = コード どう調べればいいのか分からず四苦八苦しています。どこを直せばよいでしょうか?

  • SQL文に関して教えてください。

    SQL文に関して教えてください。 SQLServer2005を利用し、マイクロソフトアクセスでadpを利用して構築を初めて行っています。 そこで、SQLServerのビューこのような事は可能でしょうか? (ビューをネストすれば出来るのですが、1つのSQL内で完結させたい) 色々探し、近い物はあったのですが、若干異なります。 フィールドがID1、ID2、ID3、date、txtと存在するとします。 ID1 ID2 date txt 1 1 20100801 test 2 1 20100901 Null 3 3 20100928 Null txtフィールドがNullのレコードを対象とし、dateが一番古い日付のレコード、nullのレコード数を 取り出す。結果としては以下が出れば正解です。 (グループ化が必要かと思います) ID1 ID2 date レコード数 2 1 20100901 2 やはり難しいでしょうか? 御教授願います。

  • MySQLのINSERT時にたまに重複になる

    下記の通り同じデータが無かった場合に限りインサートしています。 //同じデータが既にあるか確認 $sql = "select * from `reg_data` where "; $sql .= "`Date` = '".$date."' and "; $sql .= "`ID` = '".$id."' and "; $sql .= "`No` = '".$no."'"; $result = mysql_query($sql); $rows = mysql_num_rows($result); //データが0なら今日のレコード作成 if($rows == 0){ $sql = "insert into `reg_data` values('0', '".$date."', '".$id."', '".$no.")"; mysql_query($sql); } しかし、3%ぐらいの確立で重複インサートになってしまいます。 重複といっても 1個目のフィールドはAUTO_INCREMENTになっておりまして AUTO_INCREMENTの値が重複する事は無いです。 $date、$id、$noがまったく同じテーブルがいくつか重複した場合でも AUTO_INCREMENTの値は全て連番になっています。 重複インサートが発生しないよう改善するには どうしたら良いでしょうか。 日付を2フィールド目に書いているので 0時0分1秒辺りでインサートが集中してしまいます。 分散させられたら改善するような気がしますが いい案が思いつきません。 宜しくお願い致します。

    • ベストアンサー
    • PHP
  • SQL文のエラー

    PostgreSQLの初心者です。よろしくお願いします。 今、日本語ODBCドライバを使ってクライアント側を VB.NETでプログラムを作っています。PostgreSQLは8.1.4です。 レコードの追加をするために、レコードIDのMAX値を 撮るためにプログラム中にSQL sql = "SELECT MAX(user_id) AS MaxID FROM user" を入れて発行したところ、本来ですと「1」が返って こなければいけないのに、 Msgbox(MaxID) を仕込むと「0」が返ってきます。そして、その後に ERROR [HY000] Error while executing the query; ERROR; operator does not exist: # integer というエラーが返ってきます。 先ほどのSQLはリモートで直接PostgreSQLにつなぐと ちゃんと「1」が返ってくるのですが、VB.NET上では うまくいきません。 質問としては2つあります。 1)VB.NET上で実行すると、なぜ「0」が返ってきて しまうのか? 2)エラーメッセージの意味 の2点です。 よろしくお願いします。