Search code examples
mysqlsqlsortingdatesql-order-by

Sorting Events in MySQL by start and / or end date


I have the following starting position:

In a table are events with a start and end date.

I would like to sort these events in the query with the following dimensions:

current events > future events > completed events

SELECT 
    startAt,
    endAt,
    (
        CASE
            WHEN DATE(endAt) > DATE(NOW()) AND DATE(startAt) < DATE(NOW()) THEN 1
            WHEN DATE(endAt) > DATE(NOW()) AND DATE(startAt) > DATE(NOW()) THEN 0
            ELSE -1
        END
    ) as position
FROM 
    events
ORDER BY
    position DESC

Now the problem:

Sorting by the three categories works with the above query, but within the categories the following sortings must be applied:

Current events (sorted by end date) > future events (sorted by start date) > completed events (sorted by end date)

So first all running events that will expire soon will come in descending order (i.e. have more time than the previous ones), then all future events that will start soon in descending order (i.e. start later than the previous ones) and then all completed events in descending order.

SOLVED with the help of @Tim Biegeleisen

SELECT 
    startAt,
    endAt
FROM 
    events
ORDER BY
    (
        CASE
            WHEN endAt > CURDATE() AND startAt < CURDATE() THEN 1
            WHEN endAt > CURDATE() AND startAt > CURDATE() THEN 0
            ELSE -1
        END
    ) DESC,
    (
        CASE 
            WHEN startAt < CURDATE() THEN endAt 
            ELSE startAt 
        END
    ) ASC

Solution

  • You may try this logic:

    SELECT
        startAt,
        endAt
    FROM events
    ORDER BY
        CASE WHEN startAt < CURDATE() THEN endAt ELSE startAt END;
    

    The logic of the above ORDER BY clause is that if an event's start date be strictly less than right now, then it means that the event is either in progress or completely finished, in which case we sort using its endAt value. Otherwise, we sort using startAt.

    Based on your comments below, it seems that you also want to first order records by the event status, then order within each group:

    SELECT startAt, endAt
    FROM events
    ORDER BY
        CASE WHEN endAt > CURDATE() AND startAt < CURDATE() THEN 0
             WHEN endAt > CURDATE() AND startAt > CURDATE() THEN 1
             ELSE 2 END,
        CASE WHEN startAt < CURDATE() THEN endAt ELSE startAt END;