Here are my tables:
CREATE TABLE `articles` (
`id` int(10) unsigned not null auto_increment,
`author_id` int(10) unsigned not null,
`date_created` datetime not null,
PRIMARY KEY(id)
) ENGINE=InnoDB;
CREATE TABLE `article_contents` (
`article_id` int(10) unsigned not null,
`title` varchar(100) not null,
`content` text not null,
PRIMARY KEY(article_id)
) ENGINE=InnoDB;
CREATE TABLE `article_images` (
`article_id` int(10) unsigned not null,
`filename` varchar(100) not null,
`date_added` datetime not null,
UNIQUE INDEX(article_id, filename)
) ENGINE=InnoDB;
Every article can have one or more images associated with it. I’d like to display the last 40 written articles on a page, along with the most recent image associated with the article. What I can’t figure out is how to join with the article_images table, and only retrieve a single row.
Edit: It’s important that the solution performs well. The solutions I’ve seen so far — which use derived tables — take a minute or more to complete.
After looking over the other answers, it helped me realize an underlying problem.
The articles table and article_images table both need to have an additional index.
This is what you have now:
This is what you need:
articles
The new index for ordering the articles by insertion date in descending order
article_images
The first index is still needed since it will guard against attaching the another image with the same filename to an article.
The second index will make finding the most recent image simple,
With those new indexes in place, here is the query that will do your bidding:
The goal is first to create an internal subquery that only has 40 rows. That is what AA should bring back. Subquery AAA should have the article info plus the date the last image was inserted. The last set of joins should connect the 40 ids with a title and an image. The final step is to present the result set in descensding order.
Since I do not have sample data, I wrote three stored procedures in a sample database called stuff
1 to make the tables
1 to make the data
1 to run the query
Here is an example output when I ran it on my Windows Desktop (MySQL 5.5.12):
Give it a Try !!!
UPDATE
I made absolutely sure that the 40 datetimes you are reading are in fact the top 40. They are. I ran the query : select * from articles ORDER BY date_created DESC; to make sure.
UPDATE 2011-05-17 14:06
Everything works as I published before even with a larger set of images. Here is the query from the ShowLast40 Stored Procedure:
UPDATE 2011-05-17 15:16
Just for laughs, I increased the sample and reran it. Same query speed.
UPDATE 2011-05-17 15:40
Here is the new output including the date of the latest image:
Here is the new query
My query does one thing nobody else’s query does:
My query gets the last 40 articles first before joining to any other table.
Everybody else’s queries joins everything first and then attempts to do LIMIT 40 on a large temp table.
My query’s running time is not a factor of the amount of data.
Regardless of the sample size I create, my query has to be the fastest !!!