简体   繁体   English

mysql:按ID分组,每个ID获得最高优先级

[英]mysql: group by ID, get highest priority per each ID

I have the following mysql table called "pics", with the following fields and sample data: 我有以下mysql表名为“pics”,包含以下字段和示例数据:

id   vehicle_id    filename    priority
1    45            a.jpg       4
2    45            b.jpg       1
3    56            f.jpg       4
4    67            cc.jpg      4
5    45            kt.jpg      3
6    67            gg.jpg      1

Is it possible, in a single query, to get one row for each vehicle_id, and the row be the highest priority? 在单个查询中,是否可以为每个vehicle_id获取一行,并且该行是最高优先级?

The result I'm looking for: 我正在寻找的结果:

array (
  [0] => array( [id] => '2', [vehicle_id] => '45', [filename] => 'b.jpg',  [priority] => '1' ),
  [1] => array( [id] => '3', [vehicle_id] => '56', [filename] => 'f.jpg',  [priority] => '4' ),
  [2] => array( [id] => '6', [vehicle_id] => '67', [filename] => 'gg.jpg', [priority] => '1' )
);

If not possible in a single query, what would be the best approach? 如果在单个查询中不可能,那么最好的方法是什么?

Thanks! 谢谢!

This seems to be a typical max per group query. 这似乎是每组查询的典型最大值。 In most databases you could easily do this using ROW_NUMBER: 在大多数数据库中,您可以使用ROW_NUMBER轻松完成此操作:

SELECT id, vehicle_id, filename, priority
FROM (
    SELECT 
        id, vehicle_id, filename, priority,
        ROW_NUMBER() OVER (PARTITION BY vehicle_id
                           ORDER BY priority DESC, id) AS rn
    FROM pics
) AS T1
WHERE rn = 1

Since MySQL doesn't yet support ROW_NUMBER you can emulate it using variables: 由于MySQL尚不支持ROW_NUMBER,您可以使用变量来模拟它:

SELECT id, vehicle_id, filename, priority
FROM (
    SELECT
        id, vehicle_id, filename, priority,
        @rn := CASE WHEN @prev_vehicle_id = vehicle_id
                    THEN @rn + 1
                    ELSE 1
               END AS rn,
        @prev_vehicle_id := vehicle_id
    FROM (SELECT @prev_vehicle_id := NULL) vars, pics T1
    ORDER BY vehicle_id, priority DESC, id
) T2
WHERE rn = 1

Note that this method was posted before it was made clear that it is required to handle priority ties. 请注意,在明确表示需要处理优先级关系之前,已发布此方法。 I'm leaving it here for reference (see comments below). 我将它留在这里供参考(见下面的评论)。 Check out @Mark's answer for a solution that handles ties as required: 查看@ Mark的答案 ,找出根据需要处理关系的解决方案:

SELECT p.id, p.vehicle_id, p.filename, p.priority
FROM   pics p
JOIN   (
           SELECT   vehicle_id, MAX(priority) max_priority
           FROM     pics
           GROUP BY vehicle_id
       ) sub_p ON (sub_p.vehicle_id = p.vehicle_id AND 
                   sub_p.max_priority = p.priority)
GROUP BY p.vehicle_id;

This assumes that there can be no priority ties for the same vehicle_id . 这假设同一vehicle_id不存在优先级关系。

Test case: 测试用例:

CREATE TABLE pics (id int, vehicle_id int, filename varchar(10), priority int);

INSERT INTO pics VALUES ('1', '45', 'a.jpg', '4');
INSERT INTO pics VALUES ('2', '45', 'b.jpg', '1');
INSERT INTO pics VALUES ('3', '56', 'f.jpg', '4');
INSERT INTO pics VALUES ('4', '67', 'cc.jpg', '4');
INSERT INTO pics VALUES ('5', '45', 'kt.jpg', '3');
INSERT INTO pics VALUES ('6', '67', 'gg.jpg', '1');

Result: 结果:

+------+------------+----------+----------+
| id   | vehicle_id | filename | priority |
+------+------------+----------+----------+
|    1 |         45 | a.jpg    |        4 |
|    3 |         56 | f.jpg    |        4 |
|    4 |         67 | cc.jpg   |        4 |
+------+------------+----------+----------+
3 rows in set (0.01 sec)

While this may be the 'accepted' answer, the performance of Mark's solution is under normal circumstances many times better, and equally valid for the question, so by all means, go for his solution in production! 虽然这可能是“被接受”的答案,但Mark的解决方案在正常情况下的性能要好很多倍,而且对于这个问题同样有效,所以无论如何都要在生产中找到他的解决方案!


SELECT a.id, a.vehicle_id, a.filename, a.priority
FROM pics a
LEFT JOIN pics b               -- JOIN for priority
ON b.vehicle_id = a.vehicle_id 
AND b.priority > a.priority
LEFT JOIN pics c               -- JOIN for priority ties
ON c.vehicle_id = a.vehicle_id 
AND c.priority = a.priority 
AND c.id < a.id
WHERE b.id IS NULL AND c.id IS NULL

Assuming 'id' is a non-nullable column. 假设'id'是一个不可为空的列。

[edit]: my bad, need second join, cannot do it with just one. [编辑]:我的不好,需要第二次加入,不能只用一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM