mysql 将行组合在一起进行排序

o8x7eapl  于 2023-05-16  发布在  Mysql
关注(0)|答案(3)|浏览(205)

有复杂的订单问题。
下面是结构和数据:

CREATE TABLE `mail_test` (
  `id` int(10) UNSIGNED NOT NULL,
  `account_id` int(10) UNSIGNED NOT NULL,
  `score` float UNSIGNED NOT NULL,
  `from` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `mail_test` (`id`, `account_id`, `score`, `from`) VALUES
(1, 1, 0, 'a@a.com'),
(2, 2, 0, 'b@b.com'),
(3, 3, 3, 'c@c.com'),
(4, 5, 4, 'm@m.com'),
(5, 3, 1, 'c@c.com'),
(6, 9, 0.5, 'z@z.com'),
(7, 9, 3, 'z@p.com'),
(8, 8, 2, 'z@p.com');

所需输出:

(4, 5, 4, 'm@m.com'),
(7, 9, 3, 'z@p.com'),
(3, 3, 3, 'c@c.com'),
(5, 3, 1, 'c@c.com'),
(8, 8, 2, 'z@p.com');
(6, 9, 0.5, 'z@z.com'),
(1, 1, 0, 'a@a.com'),
(2, 2, 0, 'b@b.com'),

订单逻辑:首先是具有最大分数的行(父行),然后是具有与父行相同的account_idfrom的行(子行)。如果没有孩子行-再次与伟大的分数下一行。所以按分数DESC排序。但行由相同的account_idfrom分组。
mysql版本5.7

lzfw57am

lzfw57am1#

SELECT *
FROM mail_test
ORDER BY MAX(score) OVER (PARTITION BY account_id, `from`) DESC,
         account_id, `from`,
         ROW_NUMBER() OVER (PARTITION BY account_id, `from` ORDER BY score DESC)
身份证帐户ID刻痕
四个四个m@m.com
c@c.com
1c@c.com
z@p.com
z@p.com
0.5z@z.com
110a@a.com
0b@b.com

fiddle

mi7gmzs6

mi7gmzs62#

这可以通过row_number()max()来实现:

with cte as (
  select *,
           max(score) over (partition by account_id, `from`) as max_score,
           row_number() over (partition by account_id, `from` order by score, id) as rn
  from mail_test
)
select id, account_id, score, `from`
from cte
order by max_score desc, rn desc

这是mysql 5.7的一个工作解决方案:

select mt.*
from `mail_test` mt
inner join (
  select account_id, `from`, max(score) as max_score
  from `mail_test`
  group by account_id, `from`
) as s on s.account_id = mt.account_id and s.`from` = mt.`from`
order by max_score desc, id

结果:

id  account_id  score   from
4   5           4       m@m.com
3   3           3       c@c.com
5   3           1       c@c.com
7   9           3       z@p.com
8   8           2       z@p.com
6   9           0.5     z@z.com
1   1           0       a@a.com
2   2           0       b@b.com

Demo here

vlju58qv

vlju58qv3#

此版本不支持分区:

SELECT m.`id`, m.`account_id`, m.`score`, m.`from`
FROM mail_test m
LEFT JOIN mail_test parent_m
  ON m.account_id = parent_m.account_id
  AND m.from = parent_m.from
  AND m.score < parent_m.score
GROUP BY m.id, m.account_id, m.score, m.from
ORDER BY IFNULL(MAX(parent_m.score), m.`score`) DESC

相关问题