よくありますよね。履歴テーブルの最新を取りたいってやつ。履歴テーブルを顧客で集計して、その最新の履歴をゲットしたい。こういうやつだ。
select id, user_id, access_path, created from logs where year(created) = 2015 group by user_id order by id desc
logsテーブルをuser_idで集計してまとめ上げ、その中の最新のレコードをorder byで習得する。が、このSQLは全く機能しません。MySQLだけなのか、他のDBMSでも機能しないのかはわかりませんが、手元のMySQL5.6系ではgroup byされた段階で「最も古い」idが取得された。最古のレコードの値が入るみたい。
SQLで頑張る
本件を解決するには、こういうSQLを発行します。FROM句を予め絞って取得して最新の順番で並べておいて、そこからgroup byすると集計される。
select * from ( select id, user_id, access_path, created from logs where year(created) = 2015 order by id desc ) as tmp_table group by user_id
SQLで頑張らない
SQLで頑張らない場合は、group byを諦める。とりあえず最新の順番でレコードを取ってきて、プログラムでgroup byする。
リストをuser_idでgroupbyすると、user_idがキーとなるリストに分割される。それをループして更に最新のレコードのみを抽出すると、欲しかったuser_id毎の最新のレコードの一覧表を生成することが出来ます。
Pythonにはリスト操作でgroupbyっていう関数がある。こんな感じで使います。
# sampleにはSQLでソート済の配列が入っている前提です import itertools group_bys = itertools.groupby(sample, key=lambda x: x.user_id) group_by_list = [] for key,main in group_by_unit_prices: for sub in main: # 最初の要素=最新のレコード # appendしたら内側のループは終わり group_by_list.append(sub) break