Given the following tables:
CREATE TABLE IF NOT EXISTS `rank` (
`rank_id` bigint(20) NOT NULL AUTO_INCREMENT,
`rank` int(10) NOT NULL DEFAULT '0',
`subject_id` int(10) NOT NULL DEFAULT '0',
`title_id` int(10) NOT NULL DEFAULT '0',
`source_id` int(10) NOT NULL DEFAULT '0'
PRIMARY KEY (`rank_id`)
) ENGINE=MyISAM;
INSERT INTO `rank` (`rank_id`, `rank`, `subject_id`, `title_id`, `source_id`) VALUES
(23, 0, 2, 1, 1),
(22, 0, 1, 1, 1),
(15, 0, 2, 2, 2),
(14, 0, 2, 2, 1),
(20, 0, 1, 3, 2),
(18, 0, 1, 4, 2),
(19, 0, 1, 5, 2),
(21, 0, 1, 3, 1),
(24, 0, 1, 6, 2);
CREATE TABLE IF NOT EXISTS `title` (
`title_id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`description` text,
`pre` varchar(255) DEFAULT NULL,
`last_modified_by` varchar(50) DEFAULT NULL,
`last_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`title_id`)
) ENGINE=MyISAM;
INSERT INTO `title` (`title_id`, `title`, `last_modified`) VALUES
(1, 'new item', ' ', '2011-10-20 19:10:48'),
(2, 'another test', '2011-10-20 19:10:48'),
(3, 'and yet another', '2011-10-20 19:10:48'),
(4, 'one more', ' ', '2011-10-20 19:10:48'),
(5, 'adding more', ' ', '2011-10-20 19:10:48'),
(6, 'yes, another', ' ', '2011-10-20 19:10:48'),
(7, 'well, let''s see', ' ', '2011-10-20 19:10:48');
My need is for a query to select all titles that are not connected to a given subject in the rank table.
I have this working via a subquery:
SELECT title_id, title FROM title
WHERE title_id NOT IN (SELECT title_id FROM rank WHERE subject_id=2)
This returns the desired list:
+----------+-----------------+ | title_id | title | +----------+-----------------+ | 3 | and yet another | | 4 | one more | | 5 | adding more | | 6 | yes, another | | 7 | well, let's see | +----------+-----------------+
However, it gets a little slow when a large set of data is queried.
My question is if there is a way to return this result without the use of a subquery and if this alternative is any speedier.
Thanks in advance.
MySQL is usually faster with joins, though faster sub-queries are work in progress.
As usual, you’ll need to set up indexes on the foreign key (rank.title_id) and probably on the queried key (rank.subject_id).
You should read the MySQL documentation on
[LEFT JOIN][1]if you want more details. There’s also a nice trick withONthat makes it different fromWHERE.