2012-02-20 44 views
5

Tôi đã thấy khá một số giải pháp về các loại vấn đề, nhưng không ai trong số này dường như thích hợp:Chọn hàng với Max Giá trị được phân nhóm theo hai cột

Tôi có bảng sau bố trí, một phiên bản của file đính kèm, được liên kết với các đơn vị:

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

Output nên Max số phiên bản, nhóm lại theo GROUP_ID và ENTITY_ID, tôi chỉ cần một danh sách cho entity_ids duy nhất nếu giúp:

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

Những gì tôi đã đưa ra là tự này tham gia vào một:

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 

Nhưng cái này chỉ hoạt động nếu thực thể khác nhau không chia sẻ số cùng một nhóm. Điều này, thật không may là cần thiết.

Tôi đã xem xét giải pháp làm việc trong khi tạo chế độ xem nhưng điều này không được hỗ trợ trong thiết lập hiện tại của tôi.

Bất kỳ ý tưởng nào được đánh giá cao. Cảm ơn!

Trả lời

3

Hãy thử điều này:

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

Cảm ơn bạn! Đây là một giải pháp rất đơn giản. –

+0

Tôi sẽ ít nhất đảm bảo bạn thêm khóa mà tôi đề xuất để duy trì hiệu suất bảng, vì vậy entitiy_id, group_id và version_number. Trong câu hỏi của bạn, bạn đã chỉ định nó là dành cho id thực thể duy nhất và tùy chọn này sẽ hoạt động chậm hơn các đề xuất khác ở khối lượng bảng cao hơn do entity_id không được sử dụng để giới hạn tham gia. –

+0

-1 cho Không ANSI –

2

này sẽ làm việc để lựa chọn tất cả

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 

Mở rộng này để chỉ tìm kiếm một entitiy_id duy nhất sẽ chỉ đơn giản đòi hỏi thêm một WHERE vào subquery, vì vậy đây sẽ cung cấp cho

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 

Nếu bạn muốn để đảm bảo rằng điều này tiếp tục hoạt động nhanh khi số lượng hàng tăng lên, tôi khuyên bạn nên thêm khóa vào tệp đính kèm với các hàng (entitiy_id, group_id, max_version) khi truy vấn con sẽ có thể dựa vào đó để đảm bảo không khóa lên bàn.

2

này sẽ làm các trick:

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

Bạn cũng có thể giải quyết việc này bằng cách sử dụng hiệu suất cao Bảng Common Expression (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 

Hoặc

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 
Các vấn đề liên quan