skip to Main Content
select *
from table
where '2022-09-30 13:05:30.000' between concat(start_date, ' 00:00:00.000') 
and concat(end_date, ' 23:59:59.999')

The above example does not use index because it uses the concat function What should I do?
start_date, end_date type ‘yyyy-MM-dd’

2

Answers


  1. Convert to DATETIME using STR_TO_DATE

    SELECT
        *
    FROM
        `table`
    WHERE
        STR_TO_DATE(
            '2022-09-30 13:05:30.000', '%Y-%m-%d %H:%i:%s.%f'
        ) BETWEEN STR_TO_DATE(
            CONCAT(start_date, ' 00:00:00.000'), '%Y-%m-%d %H:%i:%s.%f'
        )
        AND STR_TO_DATE(
            CONCAT(end_date, ' 23:59:59.999'), '%Y-%m-%d %H:%i:%s.%f'
        )
    
    Login or Signup to reply.
  2. The query needs to avoid manipulating columns inside the WHERE. That makes the condition not sargable

    Please clarify what datatypes are being used. It seems that start_date and end_date are DATE, not DATATIME. Yet the literal ‘2022-09-30 13:05:30.000’ seems to be a DATATIME (more specifically DATETIME(3))

    A DATE and a DATETIME can be compared, so this is fine without tacking on the 0 time:

    start_date >= '2022-09-30 13:05:30.000'
    

    except that that will not catch anything from the 30th.

    The other end is messier, since a DATE maps to midnight of the morning of that date. Either of these works:

    end_date > '2022-09-30'
    end_date > '2022-09-30 13:05:30.000'
    

    Except that your "end_date" is probably set to ‘2022-09-30’, implying "any time that day"?

    end_date >= DATE('2022-09-30 13:05:30.000')
    

    also works. Now it is "sargable" because the Optimizer can evaluate DATE(constant) before trying to perform the query.

    But… What is the index? There _is no index for "betweenness" on dates or datetimes". The Optimizer does not have the concept, for example, that an "end date" is always later than a "start date". And many other assumptions.

    Even if you have an index involving start_date and/or end_date, only one of them will be used. This is because the Optimizer has no way to do two "range" tests at the same time. If it uses one of them, then it is likely to be scanning the first half or the last half of the table. At this point, it won’t bother wasting time with the index.

    If you would care to describe the application further, I may have some other tricks up my sleeve. Here’s one that is very efficient (but complex) for a similar task: http://mysql.rjweb.org/doc.php/ipranges

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search