Fetch a random row from the database without using triggers, and quickly.
First: the don'ts.
- Don't use ORDER BY RAND(). It's super slow on tables with lots of rows (lots = 2)
- Don't use WHERE id = (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM table)). If you've got any gaps, the gaps will result in a skewed probability.
- Avoid triggers that maintain a hash-like lookup table. This solves the id gap problem, but now you've got another table to maintain and you can't use a MyISAM engine. Besides, “Triggers? Boo!” is good policy when working in a web-based MVC framework, which I am.
So what to do? Let's look at a half-decent PHP implementation (this is gonna use an Orm that wraps PDO, so don't be surprised if you don't recognize the classes and methods).
$ids = Query::fetchOnly('SELECT id FROM tips'); // that's right, all of 'em!$random_id = $ids[ array_rand($ids) ];$row = Query::fetchOne('SELECT * FROM tips WHERE id = ?', $random_id);
This is actually pretty fast – to a point (100,000s of rows => problem), but the idea is sound. Select a random id, and fetch that row. How can we do this using MySQL?
Hmm... humm. AH! OFFSET! That's pretty much the same thing, right?
$count = Query::fetchOnly('SELECT COUNT(*) FROM tips');$random_offset = rand(0, $count) - 1;$row = Query::fetchOne('SELECT * FROM tips LIMIT 1 OFFSET '. (int)$random_offset);
We are essentially doing the same process we did above - fetching by a random offset - but instead of a php array, we're looking at the entire result set.
And that should do it!
This doesn't tackle the problem of selecting more than one row, and if you want to join on a has_many or many_to_many relationship, you'll need to take a few more steps (use a subquery!).
Posted in: Database Administration, Programming
2 responses to "Fetch a random row from the database without using triggers, and quickly."
Steve (7/16/2010 @ 2:13pm)
Liking Ivy more and more every day ;)
Ivy (3/18/2010 @ 7:51pm)
Wow, that looks super easy. (wink) Don't expect a normal human to understand a word of what you just wrote. My head just exploded.
Leave a Comment
Got a comment? Want a quote?
Email or call 303.952.7490
Search Blog
Archive
Categories
Credit Union Marketing (1)
Database Administration (3)
Denver Advertising (7)
Denver Internet Marketing (25)
Denver SEO (51)
Denver Web Design (13)
Denver Web Development (21)
Information Architecture (4)
Integrated Interactive (7)
Lead Generation (5)
Non-Profit Marketing (3)
Programming (16)
SEO Advice (43)
Social Media Marketing (13)
Usability (11)
Web Design (4)
Tags
Ad Extensions AdWords awards B2B Internet Marketing Binary Blogging careers database denver advertising agency Denver Interactive Agencies Denver Interactive Agency Denver Internet Marketing Denver Internet Marketing advice denver ppc denver ppc advertising denver programming denver programming jobs Denver search engine marketing Denver Search Engine Optimization Denver SEO denver seo agency Denver SEO intern denver social media Denver social media marketing Denver Software Development Denver Usability Denver web design Denver Web Development denver web sites Denver website design Fusionbox Fusionbox Framework google grants Google rankings HTML pages information architecture Internet Marketing JavaScript jobs keyword research link building linkbuilding mobile web applications Non Profit Marketing online reputation management Pay per Click PDF pages PHP development post launch checklist PPC pre launch checklist Programming Project Management pubcon Python jobs Ruby jobs search engine optimization SEO SEO advice seo-friendly urls social media advice Social Media Marketing Social Media Marketing for Credit Unions social media sharing SQL stock photos TextMate Top B2B Interactive Agencies web design Web Development web development jobs WORM

Posted by 

