[SQLite]レコードの内新しい方から指定した件数残すには?
SQLとか昔は仕事とかでそれなりに使ってたのですが、ほぼ完全に忘れてしまっていて(汗)新たに試行錯誤勉強しながら使ってみている今日この頃です。orz
さてさて、楽天やアマゾンでよく見る「最近チェックした商品」みたいな事をする場合、チェックした商品のitemCodeとかをDBに突っ込んでいくわけですが、それだとどんどん止め処も無く追加されて行っちゃうわけです。それだとまずいのでチェックした日付の新しいものから数件だけ残すようにする場合のSQLを書いてみました。いろいろやり方はあると思いますが、とりあえず下のSQLで上手くいくようです。
check_infoテーブルをuserIDが「1」をキーにチェックした日付で降順にソートして表示するSQL。
11件のレコードが有ります。
sqlite> select itemCode, lastCheckDate from check_info where userID=’1′ order by lastCheckDate desc;
book:11343487|2008/03/30 00:38:31
book:11542380|2008/03/29 23:41:33
book:11257042|2008/03/29 23:40:13
book:11257013|2008/03/29 23:38:47
book:11324182|2008/03/29 23:38:04
book:10184762|2008/03/29 20:22:02
book:11038645|2008/03/29 20:21:39
book:11206206|2008/03/29 20:18:13
book:10184759|2008/03/29 20:18:06
book:10184759|2008/03/29 20:17:58
book:11917768|2008/03/29 20:15:35
userIDが「1」でチェック日付が新しい方から5件以降を削除するSQL。
IN句はその後の副問い合わせの複数の結果を返す。
userIDと副問い合わせで返って来たitemCodeでユニークになるレコードを削除する。
LIMITに負の値をセットすると無制限OFFSET 5は頭の5レコードをすっ飛ばしてそれ以降のレコードを対象にする為の指定。
sqlite> delete from check_info WHERE userID=’1′ and itemCode IN (select itemCode from check_info where userID=’1′ order by lastCheckDate desc LIMIT -1 OFFSET 5);
ちゃん新しい方から5件残ってるかselectしてチェック
sqlite> select itemCode, lastCheckDate from check_info where userID=’1′ order by lastCheckDate desc;
book:11343487|2008/03/30 00:38:31
book:11542380|2008/03/29 23:41:33
book:11257042|2008/03/29 23:40:13
book:11257013|2008/03/29 23:38:47
book:11324182|2008/03/29 23:38:04
sqlite>
上手く行った。
1年前の記事に今頃すいません
これって5件目と6件目が同じitemcodeだと4件になっちゃいませんか?
簡単にいえば、全部おんなじitemcodeだと全部消えますよね?
lastCheckDateの方が被害は少ないかもしれませんね。
(1秒間に複数アクセスされたら同じ事が起きますが。)
おっしゃるとおりですね、同じitemCodeのレコードが続くと全部消えてしまうはずです。実際上のデータだとセレクトしたデータが9レコード目と10レコード目で同じitemCodeが出てたりしてちょっとサンプルのデータに問題がありますが、実際には、ユーザIDに対して同じitemCodeのレコードが存在しないように、データの追加処理では同じitemCodeがある場合はUPDATE、新規の場合はINSERTとitemCodeがユニークになるようにする必要があるかと思います。と言いますか、そうしないと、最近チェックしたデータが全部同じものではあまり意味がなくなるので実際そうしています。