Search code examples
mysqlsql-order-byhavingsql-in

mysql force order of results found to match order of IN clause


This question is different to a commonly asked question about ordering the final results by the IN clause.

I would like to force the results returned by the query that contains the IN clause, to match the order of the IN clause.

This is the original question that I am working from.

I'd like to alter the query below so that a row containing progress=2 occurs before progress=4 and progress=7 for each session_id when ordering the formation_page_hits table by datetime.

Here is the current query:

SELECT  COUNT(*)
FROM    (
    SELECT  session_id
    FROM    formation_page_hits
    WHERE   progress IN (2, 4, 7)
            AND datetime >= '2011-03-23'
            AND datetime < '2011-03-24'
    GROUP BY
            session_id
    HAVING  COUNT(DISTINCT progress) = 3
    ) q

These entries

datetime,               session_id, progress
('2011-03-01 01:02:11', 'abc',      2)
('2011-03-01 01:02:12', 'abc',      4)
('2011-03-01 01:02:13', 'abc',      7)

should be a match for the query, but:

datetime,               session_id, progress
('2011-03-01 01:02:11', 'abc',      4)
('2011-03-01 01:02:12', 'abc',      2)
('2011-03-01 01:02:13', 'abc',      7)

should not be a match.

Additionally:

datetime,               session_id, progress
('2011-03-01 01:02:11', 'abc',      4)
('2011-03-01 01:02:12', 'abc',      2)
('2011-03-01 01:02:13', 'abc',      4)
('2011-03-01 01:02:14', 'abc',      7)

should be a match.


Solution

  • The more common way is to double self-join to end up with a three way join ON ascending date time. That, however, is hardly a well performing query.

    select *
    from
    (
        SELECT  session_id, group_concat(concat('|',progress,'/') order by datetime) list
        FROM    formation_page_hits
        WHERE   progress IN (2, 4, 7)
                AND datetime >= '2011-03-23'
                AND datetime < '2011-03-24'
        GROUP BY session_id
        HAVING  COUNT(DISTINCT progress) = 3
    ) X
    where list like '%|2/%|4/%|7/%'