Is there a performance friendly way to list results for each letter in the database?

StackOverflow https://stackoverflow.com/questions/10097931

  •  30-05-2021
  •  | 
  •  

Question

I want to create an index page with a couple of results for each letter of the alphabet.

At the moment I have this:

SELECT url_slug, name FROM artists WHERE name LIKE "A%" ORDER BY rand() LIMIT 10 
SELECT url_slug, name FROM artists WHERE name LIKE "B%" ORDER BY rand() LIMIT 10 
SELECT url_slug, name FROM artists WHERE name LIKE "C%" ORDER BY rand() LIMIT 10 
SELECT url_slug, name FROM artists WHERE name LIKE "D%" ORDER BY rand() LIMIT 10 
SELECT url_slug, name FROM artists WHERE name LIKE "E%" ORDER BY rand() LIMIT 10 
SELECT url_slug, name FROM artists WHERE name LIKE "F%" ORDER BY rand() LIMIT 10 

Is there another, a more performance friendly, way to achieve this?

P.s. I know 'order by rand()' isn't very good. But this is just in development.

Was it helpful?

Solution

For the purpose you are trying to get, the query does not get better than that IMO. However, if the table is enormous, if might want to make occasional cache table holding the values of a fixed letter separately.

And indexing, index you records, as per the fields.

OTHER TIPS

Give this a shot, it worked against my test data:

SELECT url_slug, name FROM artists WHERE name REGEXP '^[A-Z]';

-- Update --

I got a query which will pull all the names (no limit) and group them by letter, but without the limit, may not be worth while.

# Note, you do not need the WHERE clause if you want all letters
# I left it in for dev testing
select GROUP_CONCAT(CONCAT(url_slug, ':', name)) AS list, substr(name, 1, 1) as letter from artists where name REGEXP '^[A-B]' group by letter;

What you could do is issue a query like this every couple of hours and cache the results by letter. I agree with you though, I think it's better to query once, rather than query 26 times, and as long as you are not pulling in a huge result set for every query, I think it would be ok to do to populate cache.

I'm not are what you mean by a "couple of results" for each letter, but is it possible you could do something like this:

select left(name, 1), url_slug, group_concat(name) 
from artists 
group by left(name, 1);

That gets you all the artists by each letter.

Not a good performer (26K records takes 0.04s on my netbook) but fun and slightly faster than your 26 queries -

SELECT
    url_slug, name,
    IF( @prev <> LEFT(name, 1), @rownum := 1, @rownum := @rownum+1 ) AS rank,
    @prev := LEFT(name, 1)
FROM(
    SELECT * FROM artists ORDER BY LEFT(name, 1), RAND()
) tmp, (SELECT @rownum := NULL, @prev := '') init
HAVING rank <= 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top