ORDER BY на основе нескольких случаев WHERE, возможно ли это? - PullRequest
0 голосов
/ 01 апреля 2019

Мероприятия могут быть однодневными или продолжающимися. Это означает, что иногда события могут длиться несколько дней, недель или месяцев.

Как и сейчас, можно отсортировать результат запроса по END в порядке возрастания (те, у которых истекает ранее, сначала показывается) или по START в ASC (события основаны на дате начала). Однако в обоих случаях у меня есть ограничения, которые я пытаюсь уменьшить настолько, насколько смогу.

При сортировке по 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 дней с сегодняшнего дня.

Ответы [ 3 ]

3 голосов
/ 01 апреля 2019

В зависимости от вашей базы данных 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

Вероятно, сортировка не нужна, но если вы получите результат не в порядке 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 голосов
/ 01 апреля 2019

Вы можете попробовать использовать 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 *, лучше явно перечислить столбцы, которые вы хотите.

1 голос
/ 01 апреля 2019

Я предполагаю, что вы используете MySQL.

используйте case when .. then .. end в предложении select, затем упорядочите по этому столбцу.

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

Кроме того, вы можете использовать case в предложении order by.

Примечание : я не позаботился о вашей бизнес-логике, поэтому протестируйте ее хорошо, просто расскажу, как вы можете ее достичь, надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...