通过在MySQL上开始和结束日期的复杂排序顺序

时间:2016-05-21 06:28:47

标签: mysql database sql-order-by

我有一个包含starting_dateending_date的活动表。我希望按以下方式对它们进行排序:

3组行,它们应按顺序出现,每组都按顺序显示。 群组如下:

  • 第1组:starting_date = curdate() and ending_date = curdate()。它的行应按id asc排序。

  • 第2组:starting_date <= curdate() and ending_date > curdate()。它的元素应按ending_date asc

  • 排序
  • 第3组:starting_date > curdate()。它的元素应按starting date asc

  • 排序

假设今天是may 21,这是我需要的输出样本:

| id | starting_date | ending_date |

// Group 1
| 1  |    may 21     |    may 21   |
| 2  |    may 21     |    may 21   |

// Group 2
| *  |    may 20     |    may 23   |
| *  |    may 15     |    may 25   |
| *  |    may 17     |    may 26   |
| *  |    may 21     |    may 27   |

// Group 3
| *  |    may 23     |    may 25   |
| *  |    may 24     |    may 25   |

如您所见,每个组按顺序出现,组内的每一行按指定的order by排序。

到目前为止,我已尝试使用ORDER BY CASE WHEN句,但我发现自己无法理解是否应该:

  • CASE ... END
  • 下使用多个ORDER BY语句
  • WHEN ... THEN
  • 中使用多个ORDER BY CASE ... END语句
  • 两者都有多个CASE,每个when内有多个ORDER BY
  • 使用SELECT无法完成此操作。

这是我尝试过的select events.id, events.starting_date, events.ending_date from events where events.ending_date >= CURDATE() order by case when (events.starting_date = curdate() and events.ending_date = (curdate() + interval 23 hour + interval 59 minute)) then 0 when (events.starting_date <= curdate() and events.ending_date > curdate()) then 1 when (events.starting_date > curdate()) then 2 end asc 个句子之一:

order by

    case when (events.starting_date = curdate() and events.ending_date = (curdate() + interval 23 hour + interval 59 minute)) then events.id end asc,
    case when (events.starting_date <= curdate() and events.ending_date > curdate()) then events.ending_date end asc,
    case when (events.starting_date > curdate()) then events.starting_date end asc

此查询将行放在正确的组中,但不会在各自的组中对它们进行排序。

另一个将第一组放在最后。

{{1}}

我做错了什么?

1 个答案:

答案 0 :(得分:1)

您尝试编码的排序逻辑需要两个排序变量。第一种是基于每个记录所属的组(1-3)。第二种类型发生在每个组中。正确的方法是使用您在问题中进行的两次尝试的逻辑。 ORDER BY的一般形式是:

ORDER BY group_number, something_else

其中组编号为1,2或3,其他内容是该组的特定顺序。但是这里的问题是group_numbersomething_else每个都有一个单独的CASE语句。在第1组的情况下,您需要ORDER BY 1, events.id。我还在ELSE表达式中添加了CASE条件来处理未涵盖的默认情况,任何此类记录都将显示在结果集底部的组中,按id排序。

SELECT events.id, events.starting_date, events.ending_date
FROM events
WHERE events.ending_date >= CURDATE()
ORDER BY
    (CASE
        WHEN (events.starting_date = CURDATE() AND
              events.ending_date = (CURDATE() + INTERVAL 23 HOUR + INTERVAL 59 MINUTE))
            THEN 1
        WHEN (events.starting_date <= CURDATE() AND
              events.ending_date > CURDATE())
            THEN 2
        WHEN (events.starting_date > CURDATE())
            THEN 3
        ELSE 4
    END),
    (CASE
        WHEN (events.starting_date = CURDATE() AND
              events.ending_date = (CURDATE() + INTERVAL 23 HOUR + INTERVAL 59 MINUTE))
            THEN events.id
        WHEN (events.starting_date <= CURDATE() AND
              events.ending_date > CURDATE())
            THEN events.ending_date
        WHEN (events.starting_date > CURDATE())
            THEN events.starting_date
        ELSE events.id
    END)