2012-02-20 56 views
5

我看到的这样那样的问题相当多的解决方案,但这些都不似乎是适当的:选择行

我有以下表布局,附件,这必将对实体的一个版本:

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 | 
+------+--------------+----------+----------------+---------------+ 

我已经想出这是自联接之一:

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 

但是这一个,如果不同的实体不共享同一组号码才有效。这不幸是必要的。

我在创建视图时遇到了一个工作解决方案,但在当前的设置中不支持此解决方案。

任何想法,高度赞赏。谢谢!

回答

3

试试这个:

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

谢谢!这是一个非常简单的解决方案。 – 2012-02-20 11:20:58

+0

我至少会确保你添加了我建议维护表的性能的密钥,所以entitiy_id,group_id和version_number。在您指定的问题中,它是针对单个实体ID的,并且由于entity_id没有用于限制连接,因此此选项的执行速度比其他建议在较高表格卷上的速度要慢。非ANSI的 – 2012-02-20 11:23:41

+0

-1 – 2012-02-20 11:24:10

2

这将工作选择所有

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 

扩大这只是看单个entitiy_id只会涉及添加一个WHERE到子查询,所以这会给

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

您也可以解决这个使用高性能通用表表达式(CTE)。

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