Reputation: 23
In my database, there is table called Profile
which has a DATETIME
field called birthday
.
I want to query all the records that has birthday between 05-24 and 06-07 (mm-dd
) regardless of what year it is and I used the following query:
DATE_FORMAT(`Profile`.`birthday`, "%m-%d") >= '05-24'
AND DATE_FORMAT(`Profile`.`birthday`, "%m-%d") < '06-07'
The problem is by doing this way, the index on birthday
column has no use, the query is too slow and I want to improve the speed of my query
Please show me if there is any workaround that could still do the job and improve the query performance at the same time
Upvotes: 0
Views: 1210
Reputation: 142540
Add another column
mmdd CHAR(5) CHARACTER SET ascii
and
INDEX(mmdd)
Set it using an UPDATE
with SET mmdd = DATE_FORMAT(..., "%m-%d")
As a string (CHAR
), it would compare 'correctly' unless you wrap around a year boundary (eg, November to February).
For 5.6 -- do it explicity.
For 5.7 or MariaDB -- use virtual column.
Keep in mind that if your date range is "too big" (somewhere around 2 months), the optimizer will ignore the index and do a full table scan. This is deliberate, and actually optimal.
Upvotes: 0
Reputation: 15057
Yes,
the reason is that you use a FUNCTION on a field in WHERE. This means that MySQL must read all Records of the Table (FULL TABLE SCAN).
You can add a new field birthday2 where you store only day and month with a normalized year like
UPDATE yourTable set birthday2 = DATE_FORMAT(Profile.birthday, "%m-%d-0001");
Ten you can select like
SELECT * from yourTable
WHERE birthday2 BETWEEN ''05-24-0001' AND '06-07-001';
And if you set a index on this field it will be used
Upvotes: 2