mysqlでグループ内の最大値を取得する方法

このQ&Aのポイント
  • mysqlでグループ内の最大値を取得する方法についての質問です。投票データの表において、各カテゴリの中で最も多く投票されている3人ずつを表示したいと思っています。
  • 投票データの表で各カテゴリの中で最も多く投票されている3人ずつを表示するためのSQL文を教えてください。
  • mysqlで投票データの表において、各カテゴリの中で最も多く投票されている3人ずつを表示する方法を知りたいです。
回答を見る
  • ベストアンサー

mysqlでグループ内の最大値を取得する方法

はじめまして。 voteというテーブルにcategory_id、individual_id、timeという3つのフィールドがあります。 (1)category_idは名前の通りカテゴリーのIDで、0~100まであります。 (2)individual_idはcategory_idごとに0~100まであます。 (3)timeは行が挿入された時間が記入されています。投票されるたびに行が挿入されます。 (4)category_idとindividual_idとdateでユニークキーを構成しています。 (5)category_idとindividual_idの2つで、個人が特定されます。 select categry_id, individual_id, count(*) from vote group by category_id, individual_id という命令文で、誰に何票voteされているかが分かります。 この先ですが、各カテゴリの中で最も多く投票されている3人ずつを表示したいのですが、どのようなSQLを書けばよいでしょうか。 似たような質問もあり、自分なりに四苦八苦して試してみたのですがうまくいきませんでした。 回答いただけると助かります。よろしくお願いいたします。

  • MySQL
  • 回答数2
  • ありがとう数1

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

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

4人以上を3人に絞り込むのは適当でいいとのことですので 投票数が同じ場合はユーザーのidが小さいものを上位とします 性質上一度集計をするためにviewをつくっておくとよいでしょう。 //テーブルをつくり create table vote (cID int,iID int,cTime datetime,unique(cID,iID,CTime)); //ビューをつくります create view v_vote as select cID,iID,count(*) as count from vote group by cID,iID; //ダミーデータをいれます insert ignore into vote values (1,1,'2013-01-01 00:00:00'),(1,1,'2013-01-01 00:00:01'),(1,1,'2013-01-01 00:00:02'),(1,1,'2013-01-01 00:00:03'),(1,1,'2013-01-01 00:00:04'),(1,1,'2013-01-01 00:00:05'),(1,2,'2013-01-01 00:00:06'),(1,2,'2013-01-01 00:00:07'),(1,2,'2013-01-01 00:00:08'),(1,3,'2013-01-01 00:00:09'),(1,3,'2013-01-01 00:00:10'),(1,4,'2013-01-01 00:00:11'),(1,4,'2013-01-01 00:00:12'),(1,4,'2013-01-01 00:00:13'),(2,1,'2013-01-01 00:00:14'),(2,2,'2013-01-01 00:00:15'),(2,3,'2013-01-01 00:00:16'),(2,4,'2013-01-01 00:00:17'),(2,5,'2013-01-01 00:00:18'),(2,1,'2013-01-01 00:00:19'),(3,2,'2013-01-01 00:00:20'); //まずビューを確認します select * from v_vote; //カテゴリごとにカウントの多い人順 select( select count(*) +1 from v_vote AS v2 where ( v1.count=v2.count and v1.iID>v2.iID or v1.count<v2.count ) and v1.cID=v2.cID ) AS rank ,cID,iID,count from v_vote AS v1 having rank<=3 order by cID asc,rank asc;

CPACBCEO
質問者

お礼

yambejpさんありがとうございます。 エラーも出ることなくうまく動きました。 ビューを遣うというテクニックは知りませんでした。 ありがとうございました。

その他の回答 (1)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

>最も多く投票されている3人ずつ 定義があいまい、上位3名という場合、同位のものがいた場合どうするのですか? たとえば1位が10人いたら4人目以降をどうやって除外するつもりでしょう? 新しいtimeを持つ順、古いtimeを持つ順、individual_idの昇順・降順など どれかかなぁとは思いますが・・・ あと、timeとかdateとか語句にぶれがあります。 実質datetimeのフィールドだとおもいますが、予約語をフィールド名に使うのは 混乱の元なので注意が必要です

CPACBCEO
質問者

補足

yambejpさん、コメントありがとうございます。 timeはcurrent_timestampで取得した値となっています。 なお10人同順位となった場合ですが、特にこだわらず10人中3人が選出できれば問題ないです。 例えばorder by count(*) desc limit 0, 3でmysqlが取得する値そのもので大丈夫です。 よろしくお願いいたします。

関連するQ&A

  • SQL GROUP BY

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

  • すでにあるテーブルのフィールドにユニークキーを設定できますか?

    はじめまして。 私のレンタルサーバーには最初からMYSQLというデータベースが付いています。 テーブルを設定して、すでにいくつかのデータを入力しています。 最近、重複して同じIDが入力できることに気づきました。 重複できないようにしたいと思い、調べたところ、ユニークキーというものを設定すれば重複しないらしいと言うことを知りました。 そちらのレンタルサーバーにはすでにPHPMYADMINが使えるようになっています。 PHPMYADMINをつかってIDのフィールドにユニークキーを設定しようとしました。 すると下記のようなエラーがでて、ユニークキーの設定に失敗しました。 > エラー > 実行した SQL 照会: > > ALTER TABLE `テーブルの名前` ADD UNIQUE ( > > `フィールドの名前` > ); > すでにデータが入力されているテーブルのフィールドにはユニークキーは設定できないのでしょうか? もし、すでにデータが入力されているテーブルのフィールドにユニークキーを設定する方法があったら教えてください。 もしくは私が勘違いをしている部分があったら教えて頂ければ幸いです。

    • ベストアンサー
    • MySQL
  • 一定以上の行があれば最大値を持つ行を削除するSQL

    MySQL5にて、あるテーブルの特定フィールドの数(つまりcount値)が一定値以上であれば、間引きのため別のフィールドの値で最大値をもつ行を削除するSQLを考案中です。 イメージとしては以下の通りですが、SQLとしては誤っており、また、冗長です。 DELETE FROM table WHERE id={$id} AND (SELECT COUNT(*) FROM table WHERE id={$id}) > 5 AND begin = (SELECT MAX(begin) FROM table WHERE id={$id}); よい知恵をお授けください。

    • ベストアンサー
    • MySQL
  • MySQLで別テーブルを参照し、レコードを消したい

    お世話になります。MySQL4のデータベース上に2つのテーブルがあるのですが、 片方のテーブル(a)にあるフィールド(b_id)の値を参照し、もう片方のテーブル(b)のレコードを消していきたいのです。 具体的には以下のようなテーブル(a)とテーブル(b)があります。 TBL: a =========================== id    b_id    category =========================== 0     1       3 --------------------------- 1     2       1 --------------------------- 2     3       2 --------------------------- 3     4       2 --------------------------- TBL: b =========================== id    name    price =========================== 0    goodsA   1,000 --------------------------- 1    goodsB   500 --------------------------- 2    goodsC   250 --------------------------- 3    goodsD   2,500 --------------------------- 4    goodsE    1,800 --------------------------- やりたいことは、テーブル(a)の「category」フィールドが「2」以外であれば、 そのレコードの「b_id」にある数値を「id」にもつ、テーブル(b)のレコードを消していきたいのです。 上記の例だと、テーブル(a)のid「0」と「1」がcategoryに「2」以外を持っています。 この2つのレコードのb_idは「1」と「2」ですので、テーブル(b)のid「1」と「2」を消したいと思っています。 SQLについて知識がなく、困っています。どなたかご存知の方がいらっしゃいましたら、お知恵をお貸しください。 よろしくお願いします。

  • PHPでDBの複数行更新について

    はじめまして、PHPを最近使い始めました初心者です。 [環境] PHP: 5.4.7 DB: SQLite 3.7.15.2 a  OS: Windows 7 DB上のテーブルへ複数行を挿入するソースを書いてますが 下記の文法エラーとなり行き詰っています。 [配列データとソース] Array ( [0] => Array ( [0] => 1359904500 [1] => 1359905400 [2] => 150 ) [1] => Array ( [0] => 1359990900 [1] => 1359991800 [2] => 150 ) [2] => Array ( [0] => 1360077300 [1] => 1360078200 [2] => 150 ) [3] => Array ( [0] => 1360163700 [1] => 1360164600 [2] => 150 ) 以下100件ほど続きます $sql1 = "INSERT INTO aaa (id,sstamp,estamp,data,flag) VALUES " ; $flag = 1; $count = count($time_array) ; for ( $i=1; $i< $count; $i++ ) { $sql1.= "(null,'".$time_array[$i][0]."',"."'".$time_array[$i][1]."',"."'".$time_array[$i][2]."',"."'".$flag."')," ; } $sql1 = substr($sql1, 0, -1) ; var_dump($sql1) ; $result = $db->query($sql1) ; [エラー] Warning: SQLite3::query(): Unable to prepare statement: 1, near ",": syntax error var_dumpでsql作成用変数($sql1)を見てみると問題ないように見えました。 解せないのは、変数内容をsqliteのコマンドラインへコピぺすると 正常に挿入できてしまいました。また配列を一つにしてみるとエラーなくDB挿入できました。 これよりSQL複数行挿入のvalue以下の記述が怪しいと思い、確認しましたが (aa, bb, cc), (dd, ee, ff)になっているようと思えます。 どこに問題があるかご教示をお願いいたします。

    • 締切済み
    • PHP
  • PHP MySQL で updateができません

    はじめまして。Amazon.co.jpなどでよくある 「このレビューは参考になりましたか?」 Yes/No でレビューに対する評価機能をPHPで組みたいのですが、 update set でうまくデータ更新ができず困っております。 以下ソース 【入力画面】 ----------------------------------------------------------- <? while ( $adp = mysql_fetch_array( $result6 ) ) { ?> <form name="register" action="rev.php" method="post"> //レビュー内容 <?php $str = nl2br($adp['description']); echo $description . $str ; ?> //レビュー内容 このレビューは参考になりましたか? <input type="radio" name="vote" value="2" checked>参考になった<br> <input type="radio" name="vote" value="1">参考にならなかった<br><br> <? echo $adp['add_id'] ?> <input name="add_id" type="hidden" value="<?= $adp['add_id'] ?>"> <input type="submit" value="- 登録 -"> <input type="reset" value="リセット"> </form> <? } ?> 【完了画面】 ----------------------------------------------------------- <? require( '../config.php' ); require( '../lib.php' ); $link = db_connect(); $sql = "update adp set vote = '" . mysql_real_escape_string( $_POST['vote'] ) . "' where add_id = '" . mysql_real_escape_string( $_GET['add_id'] ) . "'"; $result = mysql_query( $sql ); echo mysql_error(); // ?> 投票完了 ----------------------------------------------------------- 要するに adpのデータベースのadd_idが同じテーブルの中の voteの値を1か2に更新したいだけなのですが、 1人で色々と試してもどうしても更新できずに 困っております。 どなたかお分かりの方がいらっしゃいましたら是非 お教えいただけますと幸いです。 足りない情報などございましたらご連絡ください。 補足させていただきます。 すみません、どうかお願いします。

    • ベストアンサー
    • PHP
  • 2つのテーブルからグループ別けして集計

    こんばんは。お世話になっております。 質問のタイトルが少し変かもしれませんが、2つのテーブルがあり、 1つはカテゴリ名登録用。1つはカテゴリ別詳細データといった感じのテーブルがあるのですが、データの集計をする際、コンテンツ毎に登録された数を表示させたいのですが、登録のないデータは表示できない状態となっています。 video_category(カテゴリ登録用テーブル) cate_id  category_name 1     ハリーポッター 2     ポケモン 3     ドラえもん video(カテゴリ別詳細テーブル) no  category  title 1   1    不死鳥の騎士団    2   1    賢者の石 ※categoryは上記テーブルのcate_idと紐づけている このようなデータの場合、 ハリーポッター(2) ポケモン(0) ドラえもん(0) としたいのですが、 $sql = "select SV.`no`, SV.`category`, SV.`title`, SV.`contents`, SV.`image`, VC.`cate_id`, VC.`category_name`, count(VC.`cate_id`) as `count` from `video_category` AS VC right join `video` AS SV on SV.`category` = VC.`cate_id` group by VC.`cate_id` order by VC.`cate_id`"; だと、0値のデータが反映されません。 お恥ずかしい質問かと思いますが、ご指摘いただけると幸いです。

    • ベストアンサー
    • MySQL
  • PHP,MySQLで3つのランキング

    前提: seisekiテーブルに id(Primary), student_id(生徒ID), kamoku_id(科目ID), score, time, created のフィールドがあります。 ランキングの順位条件は、同じ科目でscoreがより高く、timeがより短く、createdがより古い方が高位となります。 同じ科目を何度でも受講できる為、student_idはユニークではありません。 前提条件から、以下3つのランキングを取得したいと考えています。 ランキング1:科目毎のランキング(同じstudent_idが1~10位独占等可) ランキング2:自分(student_id)の全受講履歴と履歴毎のランキング ランキング3:id指定時のランキング情報 各ランキングは、1SQLである必要はなく、PHPでの加工も考慮に入れております。 試行錯誤しているのですが、ORDER BY区にどうやって順位を付ければ良いのか分からず、 SELECT * FROM seiseki ORDER BY kamoku_id DESC, score DESC, time ASC, created ASC ここから進みません・・・ 何卒、よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • 数種類のテーブルの呼び出し

    こんにちは。 全く違うフィールドを含む数種類のテーブルを全て呼び出して一覧表示するためにはどういった命令を実行すればよいのでしょうか? selectはsql文の中で一度しか使えないということはわかったのですが・・・ 例えばテーブル1(フィールドはnumber,name)テーブル2(フィールドはdate,time) とした時、出力される結果としては テーブル1 number,name テーブル2 date,time ということです。 select文を2回使えるのであれば、 $sql = "select * from テーブル1 and select * from テーブル2"; という命令でいけると考えたのですが・・・

  • Access VBAで int型にnullを入れる方法について

     Access で作ったテーブルの数値型のフィールド「金額」にnullを入れたいと思い、四苦八苦しています。  以下のソースを書いたのですが、値には「0」が入ってしまい、nullが挿入されません。 Dim a As Long Dim SQL1 As String If IsNull(Me.摘要_会員番号) = True Then IsNull (a) Else a = Me.摘要_会員番号 End If SQL1 = "UPDATE 個人情報入金 SET 個人情報入金.金額 = " & a & ";" DoCmd.RunSQL SQL1  その他、a=null や、a=''をやってみたのですがこれでは入らず、String型ではないので、スペースも入りません。  nullで無くても、目で見てデータが見えない状態であればいいのですが、そのようにupdateをかける方法をしっている方、是非ご教授をお願いします。