61

私はこのようなデータベーステーブルを持っています:

id    version_id    field1    field2
1     1             texta      text1
1     2             textb      text2
2     1             textc      text3
2     2             textd      text4
2     3             texte      text5

うまくいかなかった場合は、行のいくつかのバージョンと、いくつかのテキストデータが含まれています。

クエリを実行して、各IDの番号が最も大きいバージョンを返します。(したがって、上記の2番目と最後の行のみ)。

version_id DESCで注文しながら、group byを使用してみましたが、グループ化された後に注文されているように見えるため、これは機能しません。

誰かアイデアがありますか?できないなんて信じられない!

アップデート:

これは機能しますが、サブクエリを使用します。

SELECT *
FROM (SELECT * FROM table ORDER BY version_id DESC) t1
GROUP BY t1.id
4

9 に答える 9

56

これは、列のグループごとの最大値の選択と呼ばれます。ここでは、mysql のいくつかの異なるアプローチを示します。

これが私がそれを行う方法です:

SELECT *
FROM (SELECT id, max(version_id) as version_id FROM table GROUP BY id) t1
INNER JOIN table t2 on t2.id=t1.id and t1.version_id=t2.version_id

これは比較的効率的ですが、mysql はサブクエリのためにメモリ内に一時テーブルを作成します。このテーブルの (id, version_id) に既にインデックスがあると仮定します。

このタイプの問題に対して多かれ少なかれサブクエリを使用する必要があるのは、SQL の欠陥です (セミ結合は別の例です)。

サブクエリは mysql では十分に最適化されていませんが、相関関係のないサブクエリは、メモリではなくディスクに書き込まれるほど巨大でない限り、それほど悪くはありません。このクエリでは int が 2 つしかないことを考えると、サブクエリはそれが発生するずっと前に数百万行になる可能性がありますが、最初のクエリの select * サブクエリはこの問題にずっと早く苦しむ可能性があります。

于 2009-02-11T15:09:42.627 に答える
4

これでうまくいくと思いますが、それが最善か最速かはわかりません。

SELECT * FROM table 
WHERE (id, version_id) IN 
  (SELECT id, MAX(version_id) FROM table GROUP BY id)
于 2009-02-11T15:09:54.607 に答える
2
SELECT id, version_id, field1, field2
FROM (
    SELECT @prev = id AS st, (@prev := id), m.*
    FROM (
           (SELECT @prev := NULL) p,
           (
            SELECT *
            FROM   mytable
            ORDER BY
                   id DESC, version_id DESC
           ) m
     ) m2
WHERE NOT IFNULL(st, FALSE);

サブクエリはありません。サブクエリがある場合は 1 つ渡しUNIQUE INDEX ON MYTABLE (id, version_id)ます (必要だと思います)。

于 2009-02-11T15:29:28.693 に答える
1

このクエリは、次の方法でグループなしでジョブを実行します。

SELECT * FROM table AS t
LEFT JOIN table AS t2 
    ON t.id=t2.id 
    AND t.version_id < t2.version_id
WHERE t2.id IS NULL

一時テーブルは必要ありません。

于 2012-07-23T08:48:06.147 に答える
0

これは疑似コードですが、このようなものは問題なく動作するはずです

select *
from table
inner join
(
    select id , max(version_id) maxVersion
    from table 
) dvtbl ON id = dvtbl.id && versionid = dvtbl.maxVersion
于 2009-02-11T15:10:15.183 に答える
0

私は通常、サブクエリでこれを行います:

select id, version_id, field1, field2 from datatable as dt where id = (select id from datatable where id = dt.id order by version_id desc limit 1)

于 2009-02-11T15:10:52.343 に答える
-3

テストされていませんが、次のようなものが機能する可能性があります。

SELECT*FROMテーブルGROUPBYid ORDER BY MAX(version_id)DESC

于 2009-05-08T23:13:06.233 に答える