事件可以是1天的事件,也可以是正在进行的事件。这意味着有时事件可能会持续数天,数周或数月。
现在,可以按END(升序显示)或ASC中的START(基于开始日期的事件)的升序对查询结果进行排序。但是,在这两种情况下,我都有自己的局限性,我试图尽量减少这种情况。
按END排序时,有时正在进行的事件和已经开始的事件会被推送到列表的后面。
按START排序时,已经开始且正在进行的事件最终会占据列表的第一部分。
是否可以基于逻辑而不是列链接多个ORDER BY语句?
例如:
获取在接下来的7天内到期的事件:
SELECT * FROM data WHERE end < NOW() + INTERVAL 7 DAY;
获取从今天起7天到14天之内仍在进行的事件:
SELECT * FROM data WHERE NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY;
获取所有剩余事件...
SELECT * FROM data WHERE end >= NOW() + INTERVAL 14 DAY;
基本上可以将它们合并为一个查询吗?
SELECT * FROM data
ORDER BY (logic 1), (logic 2), (logic 3);
或者,我的确可以通过运行3个独立的查询并在服务器端建立结果数组来使其工作,但是如果可能的话,我想简化我的代码。
希望最终结果将始终显示将首先在7天内到期的事件列表,然后显示在7到14天之间(可能正在开始或正在进行)的事件,然后是仍在进行或开始的事件的列表从今天起14天之后。
答案 0 :(得分:3)
根据您的SQL数据库,您可以执行以下操作:
SELECT * FROM data
WHERE (end < NOW() + INTERVAL 7 DAY) -- logic 1
or (NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY) -- logic 2
or (NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY) -- logic 3
order by
case
when (end < NOW() + INTERVAL 7 DAY) then 1
when (NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY) then 2
when (NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY) then 3
else 4
end asc
;
您也可以使用union all
:
SELECT 1 as sort_order, * FROM data
WHERE (end < NOW() + INTERVAL 7 DAY)
union all
SELECT 2 as sort_order, * FROM data
WHERE (NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY)
union all
SELECT 3 as sort_order, * FROM data
where NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY
可能不需要sort_order,但是如果您得到的结果不是select
的顺序,则可以使用子查询;数据库也会禁止您在order by
中使用union all
。
select *
from (
SELECT 1 as sort_order, * FROM data
WHERE (end < NOW() + INTERVAL 7 DAY)
union all
SELECT 2 as sort_order, * FROM data
WHERE (NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY)
union all
SELECT 3 as sort_order, * FROM data
where NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY
) order by sort_order asc -- and any other key
如果可能的话,我会亲自去找union all
(更易读)。
答案 1 :(得分:2)
您可以尝试使用UNION,在其中选择数据集,并在其中具有所需顺序的列。例如
SELECT 1 as orderby,* FROM data WHERE end < NOW() + INTERVAL 7 DAY;
UNION ALL
SELECT 2, * FROM data WHERE NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY
UNION ALL
SELECT 3, * FROM data WHERE end >= NOW() + INTERVAL 14 DAY
ORDER BY orderby, end
P.S。我建议您不要在数据库中使用SQL关键字(例如end)作为列名,这有时会引起问题,enddate会是更好的列名。
P.P.S。避免执行SELECT *,最好显式列出所需的列。
答案 2 :(得分:1)
我认为您正在使用MySQL。
在select子句中使用case when .. then .. end
,然后按此列排序。
select *, case
when end < NOW() + INTERVAL 7 DAY then 1
when NOW() + INTERVAL 7 DAY >= start AND end < NOW() + INTERVAL 14 DAY then 2
else 3 as priority
from data
order by priority
此外,您可以在order by子句中使用case
。
注意:我没有处理您的业务逻辑,因此请对其进行良好的测试,只是向您提供如何实现它,希望对您有所帮助。