【SQL】group byで指定したカラム以外のカラムの値を取得する方法

このQ&Aのポイント
  • group byで指定したカラム以外のカラムの値を取得する方法について解説します。
  • t_meisaiテーブルには調味料の使用履歴が記録されており、dateとtypeの組み合わせごとにorderの最小値を求めるSQLを使用します。
  • 求めた最小値に対応するレコードのidを抽出する方法についても説明します。
回答を見る
  • ベストアンサー

group byで指定したカラム以外のカラムの値を取得したい

t_meisaiは以下の定義で調味料の使用履歴を記録しています。 id int4 uniqueな値 date timestamp yy/mm/dd type int4 1 or 2 or 3 order int4 純粋な順番 typeには塩、砂糖のように固形のものは1、酢、醤油のように液状のものは2、それ以外は3が入ります。 orderはdate毎に使った順番が記録されていきます。 date || type のgroupごとの一番最初に使ったものだけ抽出したのが下のSQLです。 select date || type as key, min(order) from t_meisai group by key 上記の条件に当てはまるレコードのidを抽出したいのですがどうしたらよいのでしょうか?

  • yruri
  • お礼率40% (21/52)

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>クエリを実行したまま処理が戻りません。 というか、遅いんでしょう(^^;;; >下のものはgroup by keyのkeyがないのでできませんでした。 うーん、「できませんでした」って書くより、group by句を直したほうが早いですよね? select id, minorder from t_meisai t1, (select date, type, min(order) as minorder from t_meisai group by date, type) t2 where t1.date = t2.date and t1.type = t2.type

その他の回答 (1)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

min(order)が不要だったらこんなので。 select id from t_meisai t1 where exists( select date || type as key, min(order) from t_meisai t2 group by key having key = (t1.date || t1.type) ) min(order)も必要ならこんなんで select id, minorder from t_meisai t1, (select date, type, min(order) as minorder from t_meisai group by key) t2 where t1.date = t2.date and t1.type = t2.type

yruri
質問者

補足

ご回答ありがとうございます。 実は両方ともうまくいきませんでした。 上のものはhaving句のkeyが無効と言われ having key > having (t2.date || t2.type)にしましたが クエリを実行したまま処理が戻りません。 下のものはgroup by keyのkeyがないのでできませんでした。

関連するQ&A

  • group by 関数で表示するカラムを選ぶ方法

    いつもお世話になっております。 MySQLで、group by関数を使用した際の表示カラムをコントロールしたいのですが、やり方が分りません。 具体的には id | e_mail | date 1 | t1@t.jp| 2005-05-21 2 | t1@t.jp| 2005-05-22 3 | t1@t.jp| 2005-05-23 4 | t1@t.jp| 2005-05-24 5 | t1@t.jp| 2005-05-25 6 | t1@t.jp| 2005-05-26 7 | t1@t.jp| 2005-05-27 8 | t1@t.jp| 2005-05-28 というデータがあります。 このデータをe_mailでグループ化した場合に、表示されるe_mailを好きなidのものに置き換えたいのです。 通常のSQL文 select id,e_mail,date from table_name group by e_mail だと、どのidのt1@t.jpというアドレスが表示されるのかコントロールできません。 好きなidやdateのt1@t.jpというe_mailを抽出する方法をご教授頂けると大変助かります。 宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • group byのSQLでインデックスを使いたい

    group byのSQLでインデックスは使えないものなのでしょうか. Using filesortにより,全レコードを読んでしまっています. どなたか解決法を教えてください. mysql> describe xxxxx; +--------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+--------------+------+-----+---------+----------------+ | aaa_id | bigint(20) | | PRI | NULL | auto_increment | | bbb_id | bigint(20) | | MUL | 0 | | | ccc_id | bigint(20) | | MUL | 0 | | +--------+--------------+------+-----+---------+----------------+ mysql> explain select ccc_id from xxxxx group by ccc_id =2; +----+-------------+-------+-------+---------------+--------+---------+------+------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+--------+---------+------+------+----------------------------------------------+ | 1 | SIMPLE | xxxxx | index | NULL | ccc_id | 8 | NULL | 628 | Using index; Using temporary; Using filesort | +----+-------------+-------+-------+---------------+--------+---------+------+------+----------------------------------------------+

    • ベストアンサー
    • MySQL
  • [MYSQL] GROUP BY による結果レコードの取得について

    こんにちは。 今回は MYSQL の GROUP BY によって、複数レコードのグループ化を行った場合についてお尋ねしたいです。 id, val という二つのフィールドをもつテーブルがあったとして、複数レコードに対して、id でグループ化を行うとします。 その時、val の合計を求めたいのですが、 SELECT id,SUM(val) FROM tablename GROUP BY id となる SQL構文により SUM(val) を取得します。 この場合、SUM(val) を降順にソートした結果レコードを得ることはできますでしょうか? 通常は ORDER BY を用いてこれを行うと思うのですが、このケースではよくわかりません。 また、PEAR によって、これらの結果レコードを連想配列で取得しようと思っています。 結果レコード $rs に対して、 $data = $rs->fetchRow(DB_FETCHMODE_ASSOC); とすると、 $data の連想配列のキーが SUM(val) となってしまいます。 変数に括弧が含まれるのは具合がよくないので、これらを回避する方法はありませんでしょうか? 以上2点おわかりの方がいればお答えいただけないでしょうか。

    • ベストアンサー
    • PHP
  • GROUP BYで集約されるときのソートを変えたい

    GROUP BYで集約されるときのソートを変えたい MySQLの5.1を使用しています。 テーブル"tbl"には、"no","id","score"の3つのフィールドがあり、 "no"は主キーです。 +---+----+-------+ | no | id | score | +---+----+-------+ | 1 | 10 | 10002 | | 2 | 10 | 10000 | | 3 | 10 | 10008 | | 4 | 11 | 10004 | | 5 | 12 | 10006 | +---+----+-------+ 上記の表から、 scoreの値が高い順にグループ化してソートしたいのですが、 以下のSQL文ではscoreが最初に登録されたものに集約されてからグループ化されてソートしてしまうため、 思い通りの結果が得られずに困っています。 ↓具体例 SELECT no, id, score FROM tbl ORDER BY score DESC GROUP BY id; +---+----+-------+ | no | id | score | +---+----+-------+ | 5 | 12 | 10006 | | 4 | 11 | 10004 | | 1 | 10 | 10002 | +---+----+-------+ ↓欲しいソート順 +---+----+-------+ | no | id | score | +---+----+-------+ | 3 | 10 | 10008 | | 5 | 12 | 10006 | | 4 | 11 | 10004 | +---+----+-------+ テンポラリテーブルはなるべく使用せずソートしたいのですが、 このような事は可能なのでしょうか? ご存知の方がいらっしゃいましたら教えていただけると助かります。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 3つのテーブルを使ったselecct文でのorder by とgroup by の使い方について

    下記のようなSQL文を作成しましたが、 baseテーブルにあるu_dateというものでソートしたいと思っています。 u_dateは日付が入っていますが、order by だけ追加してもエラーになってしまい、group by を追加 すると、idとp_numが同じものであるのに、日付が違うものがあるので、group分けされてしまい、何個も表示されてしまいます。(idとp_numで一つのものと考えているので、一つのidに対して複数のものが選択されていることもあります) 何かよい解決策はないでしょうか? select b.id,b.name,b.p,b.a,b.i_date,w.p_name,p.p_num from base as b,win as w,pre as p where 1=1 and w.id = b.id and b.kind=1 and b.deleteflag=0 and w.win_flag=0 and p.p_num = w.p_num group by w.id,b.id,b.name,b.p,b.a,b.i_date,w.p_name,p.p_num order by w.id desc,p.p_num

  • SQLの相談

    SQLの相談です。 以下のようなテーブルについて CREATE TABLE `record`( `id` INT, `timestamp` TIMESTAMP, `point` INT ); 1) id毎に最新5件のデータを抽出 2) 合計pointが420以上のidだけを抽出 したいのですが…。 1)の処理について、うまい解決策を思いつきません。 助言をお願いします。

  • 複数テーブルで ID の一意性を保つ

    Debian GNU/Linux 3.1 で psql 8.1.2 を使用しています。 下記の要領でテーブルを作成し、2つのテーブルでIDが重ならないようにしようと意図しました。 CREATE TABLE t1 ( t1_id int2 UNIQUE NOT NULL, t1_name text NOT NULL ); NOTICE: CREATE TABLE / UNIQUE will create implicit index "t1_t1_id_key" for table "t1" CREATE TABLE CREATE TABLE t2 ( t2_id int2 UNIQUE NOT NULL, t2_name text NOT NULL ); NOTICE: CREATE TABLE / UNIQUE will create implicit index "t2_t2_id_key" for table "t2" CREATE TABLE CREATE FUNCTION unique_t12_id(int2) RETURNS BOOLEAN AS 'SELECT NOT ( EXISTS(SELECT * FROM t1 WHERE t1_id = $1) AND EXISTS(SELECT * FROM t2 WHERE t2_id = $1) );' LANGUAGE SQL; CREATE FUNCTION ALTER TABLE t1 ADD CONSTRAINT con_unique_t12 CHECK (unique_t12_id(t1_id)); ALTER TABLE ALTER TABLE t2 ADD CONSTRAINT con_unique_t12 CHECK (unique_t12_id(t2_id)); ALTER TABLE ところが実際は上手くいきませんでした。 INSERT INTO t1 VALUES(1, 'test1'); INSERT 0 1 INSERT INTO t2 VALUES(2, 'test2'); INSERT 0 1 INSERT INTO t2 VALUES(2, 'test3'); ERROR: duplicate key violates unique constraint "t2_t2_id_key" # ここまでは期待通りの挙動です INSERT INTO t2 VALUES(1, 'test4'); INSERT 0 1 ここで制約が働いて欲しかったのですが、素通りでINSERTされています。 下記のように、操作後の関数の戻り値は「偽」なのでこの操作は制約に引っかかると思うのですが 何故意図したように動かないのでしょうか。 SELECT *,unique_t12_id(t2_id) FROM t2; t2_id | t2_name | unique_t12_id -------+---------+--------------- 2 | test2 | t 1 | test4 | f (2 rows) スペースが詰まって読みづらい箇所もありますが、よろしくお願いします。

  • 日付毎の集計方法

    下記のようなテーブル構成で、過去一週間の毎日について、登録した人の数を知りたいです。 ■テーブル名 my_table システムに登録すると,IDが付与され,登録した日付が記録されます。 ---------------------------------------- id(intger) | reg_date(登録した日付,timestamp) ---------------------------------------- 以下のようなSQLを考えたのですが、timestampが「2005-12-01 00:00:00+09」という細かい日付になっているので、これでは「1日」毎の集計にはなりません。 この場合、どう表現すればよいでしょうか? SELECT sum(reg_date) from my_table where ('now' - reg_date < '7days') GROUP BY reg_date order by reg_date

  • 指定された趣味を持つメンバーがいるグループを抽出する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';

  • group byで最後のレコードを抽出したい

    group byで特定のカラムをまとめる際に、最後(最新)のレコードを抽出したいのですが 最初(古い)の行が抽出されてしまいます。 例えば、threadカラムとuptimeカラムがあるテーブルBBSで threadカラムをgroup byでまとめる際にuptimeの降順(desc)でまとめたい場合 どのようにしたらいいでしょうか? 【テーブルBBS】 id thread uptime 1 1 1230100000 2 2 1230200000 3 1 1230300000 4 3 1230400000 5 1 1230500000 6 2 1230600000 select * form bbs group by thread order by uptime desc だと thread uptime 3 1230400000 1 1230300000 2 1230200000 になってしまいます。 次のような結果を表示するにはどのようにしたらいいでしょうか。 thread uptime 2 1230600000 1 1230500000 3 1230400000 また、DISTINCTを使うと同じフィールド内に重複したレコードがある場合は最初のレコードのみ表示されますが、最後のレコードのみ表示するにはどのようにすればいいのでしょうか? よろしくお願い致します。

    • ベストアンサー
    • MySQL