• 締切済み

Groupの中の条件に合致するデータを抜き出したい

Groupの中の条件に合致するデータを抜き出したい いくつかのテーブルからGroupでくくったデータを抜き出しました。 その中から条件に合致するデータに絞りたいのですが、 思った結果となってくれません。 DB:MySQL 5.1.50 以下のようなことをしたいと考えています。 [元のデータ] ID   | 日付   | 担当   | 金額 A-01  |2010-09-01 |Angas    |1000 A-01  |2010-08-31 |Mayor    |1500 A-01  |2010-08-25 |Angas    |2000 B-01  |2010-08-30 |Roger    |1350 B-01  |2010-09-01 |Angas    |2000 B-01  |2010-08-20 |Roger    |1350 [結果として欲しいデータ] ID   | 日付   | 担当   | 金額 A-01  |2010-09-01 |Angas    |1000 A-01  |2010-08-31 |Mayor    |1500 B-01  |2010-08-30 |Roger    |1350 B-01  |2010-09-01 |Angas    |2000 ちょっとデータ例が貧弱ですが・・・ IDと担当でグループ化した中で、日付が最も大きいレコードを抜き出したい。 というのが目的です。 どのようにSQLを書くと良いのでしょうか? IDと担当でグループ化までは書けたのですが、 「グループのデータの中で日付で降順としたものの最新」というのを どのように書いたものか悩んでいます。 PS.こういうSQLの書き方で悩んだ時に、どうやって情報を集めると 良い情報に出合えるかの助言も頂ければ助かります。 よろしくお願いします。

  • nobil
  • お礼率90% (27/30)
  • MySQL
  • 回答数5
  • ありがとう数11

みんなの回答

  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.5

#3です。 >『同じテーブルを、id、担当で結びつけ、 >bにaの日付より大きなものが無い >aのデータを抽出する。』 そうですね。 自分より大きい日付が存在しない = 自分が一番大きい日付 ということです。 #2さんの書かれている、 >order by した上位のものがgroup byで優先されるという保証はありません。 >またgroup byした場合、日付と金額の紐づけも確実ではありません。 ですが、group by というのは標準のSQLでは 集約項目を除いたselect項目を全て記述する必要があります。 MYSQLではそれを拡張し、group by にない項目もselectできるようになっています。 ただし、その項目の値がグループ内で一定でない場合は結果も一定にはなりません。 下記にそのことが書かれています。 http://dev.mysql.com/doc/refman/5.1/ja/group-by-hidden-fields.html

  • moousi
  • ベストアンサー率70% (21/30)
回答No.4

#1です。 #2さんのSQLは、要件が目に見える形で素晴らしいです。 #3さんのSQLは、簡潔で素晴らしいです。 質問主さま、 #1のSQLは、悪い例として扱い参考にしてください。 自己結合がぱっと頭に浮かぶようになりたいです^^;

nobil
質問者

お礼

moousiさん、たびたびありがとうございます。 同じ結果を求めるSQLって、幾筋もあるんですね。 それだけに特性を理解していないと、結果の出方も変わるということがわかりました。 > 質問主さま、 > #1のSQLは、悪い例として扱い参考にしてください。 moousiさんに回答をつけていただいたおかげで、 これだけの別の例も見ることができましたし、 おかげで、今回の例でいくと条件の甘さも新たに見つかりました。 たとえば、max(日付)が2レコード以上の場合など。 ありがとうございます。

  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.3

not exists を使ってはどうでしょうか? select * from t1 a where  not exists(   select * from t1 b   where a.id = b.id   and a.担当 = b.担当   and a.日付 < b.日付)

nobil
質問者

お礼

yamada_gさん、回答ありがとうございます。 お礼が遅くなってすいません。 ぱっと見たときに解釈できませんでした。(^^; 『同じテーブルを、id、担当で結びつけ、 bにaの日付より大きなものが無い aのデータを抽出する。』 日本語で書くと、こんな感じでしょうか? existsって、普段は、ほとんど使ったことがありませんが、 使えそうですね。 ありがとうございます。

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

#1さんのロジックはNGのはず。 order by した上位のものがgroup byで優先されるという保証はありません。 またgroup byした場合、日付と金額の紐づけも確実ではありません。 もしやるならこんな感じになります (1)IDと担当で集計した最大の日付をだし (2)IDと担当と日付が合致するデータを抽出する select ID, 日付, 担当, 金額 from テーブル WHERE (ID,日付,担当)IN (select ID,max(日付),担当 from テーブル group by ID,担当)

nobil
質問者

お礼

yambejpさん、回答ありがとうございます。 教えていただいたSQLにフムフムと感心しております。 とっても簡単なSQLなのかもしれませんが、 なかなか慣れないと見えてこなくて・・・ ただ、ここで疑問が湧いたのですが > order by した上位のものがgroup byで優先されるという保証はありません。 > またgroup byした場合、日付と金額の紐づけも確実ではありません。 この辺の「仕様」というのは、どうやって見つけてこられるのでしょうか? #1さんから教えていただいたSQLで例示の結果が得られたのですが、 逆に得られないような場合のデータを考え中です。

  • moousi
  • ベストアンサー率70% (21/30)
回答No.1

こんな感じになると思います。 select id ID, date(date)日付, tanto 担当, amount 金額 from (select * from table1 order by date desc) a group by id,tanto; あらかじめ日付降順で並べ替えて置いたものをgroup byすると、日付が新しいものが選ばれます。 情報を集めるというか、SQL文を理解するのが結局早いのだ、と思います。 私も道半ばで、偉そうなことは言えない(^^;) ttp://www.geocities.jp/mickindex/index.html ttp://el.jibun.atmarkit.co.jp/g1sys/2009/02/sql-6be6.html 一応、テストで使ったテーブル構成を載せておきます。 create table table1 (id char(4), date datetime, tanto char(20), amount int); insert into table1 values ('A-01','2010-09-01','Angas',1000), ('A-01','2010-08-31','Mayor',1500), ('A-01','2010-08-25','Angas',2000), ('B-01','2010-08-30','Roger',1350), ('B-01','2010-09-01','Angas',2000), ('B-01','2010-08-20','Roger',1350);

nobil
質問者

お礼

moousiさん、ご回答ありがとうございます。 お礼が遅くなって申し訳ございません。 実際に、教えていただいたSQLにて結果と同様のレコードが 抽出されたことを確認いたしました。 他につけていただいた回答も参考にさせていただきます。 参考URLもありがとうございます。 やはり一番の近道は、SQLの理解ですよね。

関連するQ&A

  • <Access>2つの抽出条件が合致したデータをもってきたい

    アクセスを勉強中ですがいまいちです。 2つの抽出条件に該当するレコードを抽出させたいのですが、やり方がわかりません。 教えてください! (1)以下のようなテーブルを1枚作成。 職場名、氏名、社員No.、年、月 A-G、本多、012345、2003、10 A-G、鈴木、123456、2003、10 A-G、豊田、234567、2003、10 A-G、本多、012345、2003、11 A-G、鈴木、123456、2003、11 A-G、山羽、934567、2003、11 B-G、夏目、001234、2003、10 B-G、北原、012345、2003、10 B-G、松尾、023456、2003、10 B-G、夏目、001234、2003、11 B-G、北原、012345、2003、11 B-G、松尾、023456、2003、11 C-G、榎本、777012、2003、10 C-G、板垣、770123、2003、10 C-G、伊藤、701234、2003、10 C-G、豊田、234567、2003、11 C-G、板垣、770123、2003、11 C-G、伊藤、701234、2003、11 (2)検索フォームと結果表示フォームの2つを作成 a.結果表示フォーム  bで検索した結果を表示するフォーム(単票形式で個々の情報が表示される) b.検索フォーム  「職場」「日付」のコンボボックスと「検索」ボタンを設置。 要は、検索フォームで2つの条件(職場,日付)に合致した情報をaで表示させたい!! ですが今のところ、"職場"だけは条件通り出てくるのですが、日付が条件として読み取ってくれません。 わかるかたがいましたら、教えて頂きたいです。

  • 連続したデータを条件とするSQL文の書き方

    下記のようなデータを扱っております。 ID | Point 1 | 10 2 | 20 3 | 30 4 | 20 5 | 30 6 | 10 7 | 20 8 | 30 9 | 30 上記データにおいて、Pointが10,20,30と連続している時の Pointが30でのID値を取得するSQL文が分かりません。 上記データであれば、ID3と8が条件に合致しており、取得したいID値となります。 ID5や9はPointが30ですが、『Pointが10,20,30と連続している』という条件に合致していない為、取得したいID値ではありません。 これを叶えるSQL文を教えて頂けないでしょうか。 (SQLiteを使用しています。)

  • MySQLで特定のグループの上位3件を取得したい。

    ちょっと壁に当たったので、わかる範囲でお答え頂きたいのですが、 以下のようなテーブルがあったとします。 id user price date 1 A 1000 2013/5/31 2 A 1200 2013/6/1 3 B 1000 2013/5/20 4 A 1500 2013/5/12 5 C 1300 2013/5/31 6 C 1400 2013/5/14 7 C 1000 2013/5/6 8 B 1100 2013/5/24 9 B 1200 2013/5/30 10 B 1100 2013/5/4 11 A 1800 2013/4/12 12 C 900 2013/4/6 ・・・ 次に取得したいのは、 A 1200 2013/6/1 A 1000 2013/5/31 A 1500 2013/5/12 C 1300 2013/5/31 C 1400 2013/5/14 C 1000 2013/5/6 B 1200 2013/5/30 B 1100 2013/5/24 B 1000 2013/5/20 このようなデータなのですが、 条件: 1.userでグループ化したうちの日付降順で並べる 2.そのuserのデータの中で、日付降順で並べる 3.userのデータが複数あっても、取得するのは新しいものから3件のみ この条件を満たすSQL文はどのように記述すればよいか、お知恵をお貸し下さい。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • Excel 複数条件に合致するデータの件数を返す関数は??

    複数の条件に合致するデータの件数を出したいのですが、どうしたら良いでしょう?? データは 性別コード|年令コード 1|3 2|1 1|4 1|5 1|1 2|5 といった具合に入力されていて、 性別=1かつ年令=1 の件数はいくつか、というものを出したいのです。 配列数式で {=Count(If(A1:A10=1,B1:B10,""))} 試して見たんですが、一つの条件に合致する件数のみしかカウントできません。(例えば、性別=1の件数) 複数条件のカウントをするにはどうしたら良いでしょうか? ご存知の方がいらっしゃいましたら、教えて下さい。

  • 条件付ソートについて

    SQL文で条件付のソートについて教えてください。 テーブルA(id, data_a, data_b)があったとき、 data_aとdata_bのうち、値が大きいほうのデータでソートするためのSQL文が知りたいのです。 例えば以下のようなデータが入っていたとき、 id,date_a,date_b 1, 10, 0 2, 20, 40 3, 30, 30 4, 90, 15 以下のような結果になるようにソートしたいのです。 id,date_a,date_b 1, 10, 0 3, 30, 30 2, 20, 40 4, 90, 15 良い方法があれば教えてください。 よろしくお願いします。

  • SQLで部分的にGROUP BYしたいとき(その2

    こんばんわ。 先日こちら(http://okwave.jp/qa/q7666702.html) で質問させていただきましたが、まだ問題があったため、 再度質問させていただきます。 以下のような20カラムある「出納帳」テーブルがあって、 同一日付の金額を集約してしまいたいです。 出納帳 ID 日付   金額 伝票 ・・・(全20カラム) 1 2012/8/20 1000 A01 ・・・ 2 2012/8/20 2000 A02 ・・・ 3 2012/8/21 -1000 B01 ・・・ 4 2012/8/21 -2000 B02 ・・・ 5 2012/8/22 3000 A03 ・・・ 6 2012/8/23 4000 A04 ・・・ 7 2012/8/24 -3000 B03 ・・・ 8 2012/8/24 -4000 B04 ・・・ 9 2012/8/27 5000 A05 ・・・ ↓「日付」で金額集約 ID 日付   金額 伝票 ・・・(全20カラム) 1 2012/8/20 1000 A01 ・・・ 2 2012/8/20 2000 A02 ・・・  2012/8/21 -3000    ・・・(-1000と-2000を集約) 5 2012/8/22 3000 A03 ・・・ 6 2012/8/23 4000 A04 ・・・  2012/8/24 -7000    ・・・(-3000と-4000を集約) 9 2012/8/27 5000 A05 ・・・ と集約キー以外はNULLにしたいのですが、 またまた、 ( SELECT ID, 日付, 金額, 伝票, ・・・ FROM  出納帳 WHERE  金額>=0 UNION ALL SELECT NULL, 日付, SUM(金額), NULL, ・・・ FROM  出納帳 WHERE  金額<0 GROUP BY 日付 ) ORDER BY 日付 とUNIONをする方法しか思いつかなかったのですが、 UNIONせずに端的に表現できるSQLはありますでしょうか?

  • MySQLで顧客毎に最新のデータ順で表示

    以下のようなデータがあります。 id 顧客コード 日付 金額 1 A001 2012/12/25 100 2 B001 2012/12/24 200 3 A001 2012/12/24 100 4 C001 2012/12/23 500 5 A001 2012/12/23 300 6 B001 2012/12/23 100 このデータを、顧客毎に最新順で表示したいのです。 順番は、 1.最新の日付順に顧客がまず並ぶ 2.その顧客の並び順で、顧客毎に日付が新しい順に各データが並ぶ 説明が下手ですが、下の様に 1 A001 2012/12/25 100 3 A001 2012/12/24 100 5 A001 2012/12/23 300 2 B001 2012/12/24 200 6 B001 2012/12/23 100 4 C001 2012/12/23 500 A001、B001、C001の中で、最新の日付を持っているのがA001→B001→C001なので、その順で並ぶ。 (SELECT 顧客コード, MAX(日付) FROM tbl GROUP BY 顧客コード かな?) さらに、その顧客の中で日付順にデータが並ぶ。 このように抽出するには、どのようなSQL文で行うのでしょうか。 サブクエリを使うのかなとは思うのですが、あまり理解できていないため思いつきません。 わかるかたよろしくお願いします。

    • ベストアンサー
    • MySQL
  • EXCELで条件に合致したデータから、さらに重複するデータを1と数える

    EXCELで条件に合致したデータから、さらに重複するデータを1と数える ことが関数で出来るでしょうか? 例えば   A ,B ,C 1 見積No 、担当者、商品名 2 111、山田、パソコン 3 111、山田、プリンタ 4 222、佐藤、HDD 5 333、山田、パソコン 6 444、青木、パソコン 7 555、山田、HDD パソコンの担当者ごとの見積もり件数はという問いに対して  山田 2件  佐藤 0件  青木 1件 という解答を求めたいのです。 見積Noが同じ場合は同じ見積書で明細が2行の場合で、これを1件と数えたいのです。 フィルタで絞った後に、=SUMPRODUCT(1/COUNTIF(A2:A100,A2:A100)) という関数を試しましたが、フィルタを無視して全ての件数が対象となってしまいました。 SUMに対するSUBTOTAL関数のようなものがあれば便利だったのですが…。 うまく質問出来たのか不安ですが、判る方お願いします。 m(__)m  

  • 条件に合致した行を削除

    Excel2013 マクロをご指南ください。 A列からZ列までデータがあります。 最終行は常に変動します。 E列に日付。Z列に時刻。 全データの中で E列の日付で最も古い日付(同じ日付あり) 且つ  Z列の時刻で6:00:00(6時)以前に合致する行を削除する マクロをご教示ください。

  • グループ毎の条件抽出

    はじめまして。よろしくお願いします。 今、以下のようなデータで以下の抽出条件でデータ取得行いたいと思っています。 ■ TABLEA NO 1~n 識別 A~Z 状況 1~4(null有り) 日付 YYYY/MM/DD 1.識別毎にグループ分けをしたい。 2.「1.」の中で状況が最大値の物のみ抽出 3.「2.」の中で日付が最大値の物のみ抽出 4.識別が無いものは各行出力 5.「1.~3.」の中で抽出されたデータのTABLEAのカラムを全て取得 今は以下のようなSQLで実現させようとしておりますが、 インラインビューを何度もネストしている為あまりパフォーマンスが 良くないです。もっと効率的なSQLが在れば教えていたければと思います。 SELECT /* 4.対象TABLEAのデータを取得 */ * FROM TABLEA, /* 2.グループの中で日付日付の最大値を求める */ (SELECT MAX(TABLEA.日付) AS 最新日付, TABLEA.状況 TABLEA.識別 FROM TABLEA, /* 1.識別毎に状況の最大値を求めるグループ */ ( SELECT MAX(状況) AS 状況最大値, 識別 FROM TABLEA WHERE 識別 IS NOT NULL GROUP BY 識別 )TMP WHERE TABLEA.識別 = TMP.識別 TABLEA.状況 = TMP.状況最大値 )TMP2 TABLEA.日付 = TMP2.最新日付 TABLEA.状況 = TMP2.状況 TABLEA.識別 = TMP2.識別 /* 3.識別は無いものを取得 */ UNION SELECT * FROM TABLEA WHERE 識別 IS NULL 以上です。よろしくお願いします。