基于多个WHERE情况的ORDER BY,这可能吗?

问题描述 投票:0回答:3

活动可以是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天后开始的事件从今天开始。

mysql sql
3个回答
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(它更具可读性)。


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

附:我建议你不要在数据库中使用SQL关键字,例如end作为列名,这有时会导致问题,enddate会是一个更好的列名。

P.P.S.避免使用SELECT *,最好明确列出所需的列。


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

注意:我没有关注你的业务逻辑,所以测试得很好,只是告诉你如何实现它,希望它有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.