Reputation: 3083
I have the following query:
SELECT
b.business_name,
b.address,
b.city,
b.state,
b.phone_number,
i.date
FROM business_table b
LEFT JOIN inspection_table i ON b.id = i.business_id
WHERE i.date = (
SELECT MAX(i.date)
FROM inspection_table i
WHERE b.id = i.business_id
)
AND b.city LIKE '%Boston%'
OR b.city LIKE '%Dallas%'
OR b.city LIKE '%Seattle%'
OR b.city LIKE '%New York%'
OR b.city LIKE '%Portland%'
OR b.city LIKE '%San Antonio%'
OR b.city LIKE '%Los Angeles%'
OR b.city LIKE '%Miami%'
ORDER BY i.date DESC;
I get the result I am after but the query is very slow (~17s). Is there a better way to construct this query? The city field is indexed in the business_table.
Upvotes: 0
Views: 70
Reputation: 142518
There seem to be multiple problems in the formulation of the query. The other answers have brought out some of the fixes. I'll try to address all the problems.
Parentheses is a must -- x AND y OR z OR w
is treated as (x AND y) OR z OR w
. This may fix the intent and the performance.
You are looking for South Boston
as well as Boston
? Also Boston Heights
? If not, then get rid of the wildcards (%
). This will make it possible to index city
.
If you do need the wild cards, then using a FULLTEXT
index and MATCH...AGAINST...
will run a lot faster.
With the leading %
, I think, the REGEXP suggested Obsidian Age will be faster because it would do only one scan of city
.
If business_id
is not the PRIMARY KEY
, add these:
INDEX(business_id, date)
INDEX(business_id, city)
Upvotes: 0
Reputation: 15961
I have a feeling your OR is wrong, so this is what I think will be the better query.
SELECT
b.business_name,
b.address,
b.city,
b.state,
b.phone_number,
li.lastInspection AS `date`
FROM (SELECT business_id, MAX(i.date) as lastInspection
FROM inspection_table
GROUP BY business_id) AS li
INNER JOIN business_table b
ON li.business_id = b.business_id
WHERE b.city LIKE '%Boston%'
OR b.city LIKE '%Dallas%'
OR b.city LIKE '%Seattle%'
OR b.city LIKE '%New York%'
OR b.city LIKE '%Portland%'
OR b.city LIKE '%San Antonio%'
OR b.city LIKE '%Los Angeles%'
OR b.city LIKE '%Miami%'
ORDER BY li.lastInspection DESC
;
If you have a huge number of cities or businesses, this might be slow; but I'd wager an index on inspection_table (business_id, date)
would speed it up quite a bit.
Ideally, this will get your last inspections, find their business and then filter the businesses; if it doesn't you could force it by putting all but the WHERE conditions in a subquery, and have an outer query do the final filtering.
Upvotes: 0
Reputation: 562871
A conventional index doesn't help LIKE '%pattern'
queries at all. The index is not used, and your query must do a complete table-scan of the table.
You need to use Full-Text Search Functions if you want it to search efficiently using MySQL.
You might like my presentation Full Text Search Throwdown, in which I compare different methods of text searching for MySQL.
Upvotes: 1