简体   繁体   English

Mysql 按条件按多列排序

[英]Mysql order by multiple columns with conditions

I have application using Mysql Database with this schema for example.例如,我有使用 Mysql 数据库的应用程序和这种模式。

packages
id, name,       order
1, 'Free',      3
2, 'Basic',     2
3, 'Extensive', 1

ads
id,    date,                    package_id,   package_expires_at
1,     '2021-12-10 00:00:00',   1,            '2022-01-10'
2,     '2021-12-15 00:00:00',   3,            '2021-12-28'
3,     '2021-12-15 00:00:00',   3,            '2022-01-10'
4,     '2021-12-20 00:00:00',   2,            '2022-01-10'
5,     '2021-12-21 00:00:00',   1,            '2021-12-28'
6,     '2021-12-25 00:00:00',   1,            '2021-12-28'

What I need to achieve is selecting all ads but ordering none expired package first by packages.order asc, package_expire_at desc then order the expired by date desc我需要实现的是选择所有广告,但首先by packages.order asc, package_expire_at desc订购没有过期的 package 然后订购过期的按date desc

for example suppose we are in '2021-12-29' then the result should be例如假设我们在 '2021-12-29' 那么结果应该是

id,    date,                    package_id,   package_expires_at
3,     '2021-12-15 00:00:00',   3,            '2022-01-10'
4,     '2021-12-20 00:00:00',   2,            '2022-01-10'
1,     '2021-12-10 00:00:00',   1,            '2022-01-10'
6,     '2021-12-25 00:00:00',   1,            '2021-12-28'
5,     '2021-12-21 00:00:00',   1,            '2021-12-28'
2,     '2021-12-15 00:00:00',   3,            '2021-12-28'

I have added the schema on fiddle我在小提琴上添加了架构

http://sqlfiddle.com/#!9/cedb45/9 http://sqlfiddle.com/#!9/cedb45/9

The way you do this in (My)SQL is, you provide a virtual field as ORDER BY condition.在 (My)SQL 中执行此操作的方式是,您提供一个虚拟字段作为ORDER BY条件。 Something like this should probably do the trick:像这样的东西应该可以解决问题:

      SELECT a.id
           , a.date
           , a.package_id
           , a.package_expires_at
           , IF( a.package_expires_at < CURRENT_DATE,  1,         0                      ) AS is_expired
           , IF( a.package_expires_at < CURRENT_DATE,  a.`date`,  a.`package_expires_at` ) AS sort_date
           , p.`order`                                                                     AS sort_package_order
        FROM ads       AS  a
  INNER JOIN packages  AS  p 
          ON p.id = a.package_id
    ORDER BY IF( a.package_expires_at < CURRENT_DATE,  1,         0                      ) ASC
           , IF( a.package_expires_at < CURRENT_DATE,  1,         p.`order`              ) ASC
           , IF( a.package_expires_at < CURRENT_DATE,  a.`date`,  a.`package_expires_at` ) DESC

use two separate query and then union them (your packages order is upside down of its ids now)使用两个单独的查询,然后union它们(你的包顺序现在颠倒了它的 ID)

select * from (SELECT * from ads WHERE package_expires_at >= '2021-12-29' order by package_id asc, package_expires_at desc ) as a
union
select * from (SELECT * from ads WHERE package_expires_at < '2021-12-29' order by date desc) as b

if they are dynamic and without order, join them and then do things such as above.如果它们是动态的并且没有顺序,请加入它们,然后执行上述操作。

select * from (SELECT ads.id,date,package_id,package_expires_at from ads left outer join packages on package_id = ads.id WHERE package_expires_at >= '2021-12-29' order by packages.order asc, package_expires_at desc ) as a
union
select * from ( SELECT ads.id,date,package_id,package_expires_at from ads left outer join packages on package_id = ads.id WHERE package_expires_at < '2021-12-29' order by date desc ) as b

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

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