MySQL GROUP BYクエリで適切な行を取得する

私は、 'コメント'という名前のMySqlテーブルを持っています:

id | date       | movie_id | comment_value
1    2011/11/05   10         comment_value_1
2    2012/01/10   10         comment_value_2
3    2011/10/10   15         comment_value_3
4    2011/11/20   15         comment_value_4
5    2011/12/10   30         comment_value_5

そして、私は各映画の最新のコメントをクエリで取得しようとします:

SELECT MAX(date),id,date,movie_id,comment_value FROM comments GROUP BY movie_id

MAX(date)は最新の日付を返しますが、関連する行(movie_id、id、comment_value、date)は一致しません。次のように、ムービーの最初のコメントの値を返します。

MAX(date)  | id | date       | movie_id | comment_value
2012/01/10   1    2011/11/05   10         comment_value_1
2011/11/20   3    2011/10/10   15         comment_value_3
2011/12/10   5    2011/12/10   30         comment_value_5

だから、私の質問です:どのように私は各映画のための最新のコメントを1つのクエリ(私は実際には良いコメントを取得するために2番目のクエリを使用している)

0
はい、私は日付ごとに1映画につき1つのコメントしか持っていません。
追加された 著者 JuSchz,
日付ごとに1映画につき1つのコメントしかありませんか?同じ日に映画に複数のコメントがある場合、どのように結びつきが崩れますか、それともそれらをすべて望みますか? DATE列ではなく、完全なDATETIME列を考慮する必要があります。
追加された 著者 Marcus Adams,

4 答え

2つのクエリを使用することはそれほど悪くありません。それ以外の場合は、次のようなことができます

SELECT id, date, movie_id, comment_value FROM comments c JOIN
(SELECT movie_id, MAX(date) date FROM comments GROUP BY movie_id) x
ON x.movie_id=c.movie_id AND x.date=c.date GROUP BY movie_id;
4
追加された
私はtpolyakの答えを試みたが、うまくいかなかった...
追加された 著者 JuSchz,
@ThitLwinOo私はそれを確認します、それは最後のグループで最後に働いています。ありがとう
追加された 著者 JuSchz,
最後のグループは必要ですか?
追加された 著者 Thit Lwin Oo,
@jules、tpolyakのより良い答えをチェックしてください。
追加された 著者 Marcus Adams,
@ThitLwinOo良い点。いいえ、そうではありません。
追加された 著者 Michael Mior,

これを試して:

SELECT c1.* 
FROM comments c1 
LEFT JOIN comments c2 ON (c1.movie_id = c2.movie_id AND c1.date < c2.date)
WHERE c2.id IS NULL

結合条件のため、最大日付値を含まない行のみを結合することができるため、c2.id IS NULLを使用して行をフィルタリングすると、最大値の行が得られます。

3
追加された
私はその考えを理解していますが、私はクエリを実行すると、私の行はmovie_idによってグループ化されていません。
追加された 著者 JuSchz,
私はなぜそれが動作していないかを考え出した。 c1.id = c2.id c1.movi​​e_id = c2.movi​​e_id および c2.id IS NULL c2に置き換えてください。 movie_idはNULLです。クエリはより高速に見えます。ありがとうございました
追加された 著者 JuSchz,
@MarcusAdams本のSQL Antipatternsはよく見えます。私は今それを買うつもりだと思う:)
追加された 著者 JuSchz,
はい、movie_idは使用する正しい列です。編集していただきありがとうございます
追加された 著者 tpolyak,
+1これは、書籍「 SQL Antipatterns 」で推奨されている方法です。サブクエリを使用するよりも最適化します。
追加された 著者 Marcus Adams,
それが必要な場合は、 GROUP BY movie_id を追加する必要があります。
追加された 著者 Michael Mior,

DATEの代わりにDATETIMEフィールドを使用することは可能ですか?そうすれば、クエリの処理が簡単になり、レポート機能が向上します。 DATETIMEフィールドを必要に応じてより具体的なものに集約できます。

1
追加された
はい、DATETIMEを使用できます。しかし、私はそれがどんな違いを生むのか本当に理解していません。もっと説明できますか?
追加された 著者 JuSchz,
DATETIMEには時間(ミリ秒まで)が含まれます。したがって、コメントからSELECT MAX(日付)を実行すると、常に最新のコメントが得られます。
追加された 著者 HubblyJubbly,
create table comments (id int,movie_dt datetime,movie_id int,comment_value nvarchar(100))

insert into comments values (1,'2011/11/05',10,'comment_value_1')
insert into comments values (2,'2012/01/10',10,'comment_value_2')
insert into comments values (3,'2011/10/10',15,'comment_value_3')
insert into comments values (4,'2011/11/20',15,'comment_value_4')
insert into comments values (5,'2011/12/10',30,'comment_value_5')

select a.id, m.movie_dt, m.movie_id,a.comment_value
from comments a
inner join 
(
    SELECT MAX(movie_dt) movie_dt,movie_id
    FROM comments 
    GROUP BY movie_id
) m on (a.movie_dt = m.movie_dt and a.movie_id = m.movie_id)
0
追加された