2012-02-20 3 views
5

2列でグループ化された最大値を持つ行が、これらのどれが適切であるように思われる:を選択し、私はこの種の問題にかなりの数のソリューションを見てきました

私は次の表を持っていますレイアウト、エンティティにバインドされている添付ファイルのバージョン管理:

TABLE attachments 
+------+--------------+----------+----------------+---------------+ 
| id | entitiy_id | group_id | version_number | filename  | 
+------+--------------+----------+----------------+---------------+ 
| 1 | 1   | 1  | 1    | file1-1.pdf | 
| 2 | 1   | 1  | 2    | file1-2.pdf | 
| 3 | 1   | 2  | 1    | file2-1.pdf | 
| 4 | 2   | 1  | 1    | file1-1.pdf | 
| 5 | 2   | 1  | 2    | file1-2.pdf | 
| 6 | 2   | 3  | 1    | file3-1.pdf | 
+------+--------------+----------+----------------+---------------+ 

出力が最大のバージョン番号でなければなりませんそれが助け場合、GROUP_IDとENTITY_IDによってグループ化され、私は単一entity_idsためのリストを必要とするだけだろう:

+------+--------------+----------+----------------+---------------+ 
| id | entitiy_id | group_id | version_number | filename  | 
+------+--------------+----------+----------------+---------------+ 
| 2 | 1   | 1  | 2    | file1-2.pdf | 
| 3 | 1   | 2  | 1    | file2-1.pdf | 
| 5 | 2   | 1  | 2    | file1-2.pdf | 
| 6 | 2   | 3  | 1    | file3-1.pdf | 
+------+--------------+----------+----------------+---------------+ 

私が出ていることは、この自己では1に参加:

SELECT * 
FROM `attachments` `attachments` 
     LEFT OUTER JOIN attachments t2 
     ON (attachments.group_id = t2.group_id 
       AND attachments.version_number < t2.version_number) 
WHERE (t2.group_id IS NULL) 
    AND (`t2`.`id` = 1) 
GROUP BY t2.group_id 

しかし、異なるエンティティが同じグループ番号を共有していない場合は、この1にのみ機能します。これは残念なことに必要です。

ビューを作成中に問題の解決策を見つけましたが、現在の設定ではサポートされていません。

どのようなアイデアも高く評価されています。ありがとう!

答えて

3

はこれを試してください:あなたはまた、高性能な共通テーブル式(CTE)を使用してこの問題を解決することができます

select t1.* from attachments t1 
left join attachments t2 
on t1.entity_id = t2.entity_id and t1.group_id = t2.group_id and 
    t1.version_number < t2.version_number 
where t2.version_number is null 
+0

ありがとうございます!これは非常に簡単な解決策です。 –

+0

少なくとも、テーブルのパフォーマンスを維持するために提案したキー(entitiy_id、group_id、およびversion_number)を追加することをお勧めします。あなたの質問では、単一のエンティティIDのために指定されていました。このオプションは、結合を制限するためにentity_idが使用されていないため、より高いテーブルボリュームで他の提案より遅く実行されます。 –

+0

-1(非ANSIの場合) –

2

これは、これは単にサブクエリにWHEREを追加伴うだろう単一entitiy_idを探すために拡大し、すべての

SELECT attachments.* 
FROM (
    SELECT entitiy_id, group_id, MAX(version_number) AS max_version 
    FROM attachments 
    GROUP BY entitiy_id, group_id 
) AS maxVersions 
INNER JOIN attachments 
ON attachments.entitiy_id = maxVersions.entitiy_id 
AND attachments.group_id = maxVersions.group_id 
AND attachments.version_number = maxVersions.max_version 

を選択するために働くだろうので、あなたが望むならば、これは

SELECT attachments.* 
FROM (
    SELECT entitiy_id, group_id, MAX(version_number) AS max_version 
    FROM attachments 
    WHERE entitity_id = [[YOUR ENTITIY ID HERE]] 
    GROUP BY entitiy_id, group_id 
) AS maxVersions 
INNER JOIN attachments 
ON attachments.entitiy_id = maxVersions.entitiy_id 
AND attachments.group_id = maxVersions.group_id 
AND attachments.version_number = maxVersions.max_version 

を与えるだろう行の数が増えるにつれてこれが高速に動作することを確認するために、行(entitiy_id, group_id, max_version)を持つ添付ファイルにキーを追加することをお勧めします。そうすれば、サブクエリはそれを頼りにしてロックしないようにしますテーブルを上げる。

2

これはトリックを行うだろう:

select a1.* from attachments a1 
inner join (select entitiy_id, group_id, max(version_number) as version_number 
      from attachments 
      group by entitiy_id, group_id) a2 on a1.entitiy_id = a2.entitiy_id and 
                a1.group_id = a2.group_id and 
                a1.version_number = a2.version_number 
0

WITH CTE AS 
(
SELECT entitiy_id, group_id, version_number, filename,  
ROW_NUMBER() OVER (PARTITION BY entitiy_id, group_id ORDER BY version_number DESC) as RowNum 
FROM attachments 
) 
SELECT entitiy_id, group_id, version_number, filename 
FROM CTE 
WHERE RowNum = 1 

それとも

SELECT T.entitiy_id, T.group_id, T.version_number, T.filename 
FROM (SELECT entitiy_id, group_id, version_number, filename,  
    ROW_NUMBER() OVER (PARTITION BY entitiy_id, group_id ORDER BY version_number DESC) as RowNum 
    FROM attachments 
    ) as T 
WHERE RowNum = 1 
関連する問題