Reputation: 5006
I have 2 tables:
$sql = "CREATE TABLE $media_table (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(50) NOT NULL,
`title` varchar(255) DEFAULT NULL,
`description` varchar(2000) DEFAULT NULL,
`playlist_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `playlist_id` (`playlist_id`),
) $charset_collate;";
$sql = "CREATE TABLE $taxonomy_table (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(10) NOT NULL,
`title` varchar(500) NOT NULL,
`media_id` int(11) NOT NULL,
`playlist_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `media_id` (`media_id`),
CONSTRAINT `mvp_taxonomy_ibfk_1` FOREIGN KEY (`media_id`) REFERENCES {$media_table} (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) $charset_collate;";
Let say I want to select all rows from media_table where playlist_id=5 and title from taxonomy_table="sport, football".
I could run 2 queries, first get all media_id from taxonomy_table where title="..." AND playlist_id="5", then second query select all rows from media_table WHERE id IN (ids).
Does this belongs to some kind of JOIN query maybe?
I tried this but I am not getting desired results:
$query = "SELECT * FROM {$media_table}
INNER JOIN {$taxonomy_table}
ON {$media_table}.id = {$taxonomy_table}.media_id
WHERE {$taxonomy_table}.type='tag' AND {$taxonomy_table}.title IN ($arg) AND {$taxonomy_table}.playlist_id=%d
ORDER BY {$media_table}.order_id";
It seems like its mixing all columns from both tables into the results, but I only want to retrieve rows from media_table that have title(s) from taxonomy_table.
Upvotes: 0
Views: 45
Reputation: 59
It seems like its mixing all columns from both tables into the results, but I only want to retrieve rows from media_table that have title(s) from taxonomy_table.
Reason is that the join enables you to select data from both tables. The trick in this case is to change the asterisk (*) to specific columns or to use a prefix for the asterisk.
examples for using a prefix:
$query = "SELECT {$media_table}.* FROM {$media_table}
INNER JOIN {$taxonomy_table}
ON {$media_table}.id = {$taxonomy_table}.media_id
`WHERE {$taxonomy_table}.type='tag' AND {$taxonomy_table}.title IN ($arg) AND` {$taxonomy_table}.playlist_id=%d
ORDER BY {$media_table}.order_id";
or
$query = "SELECT t1.* FROM {$media_table} t1
INNER JOIN {$taxonomy_table} t2
ON t1.id = t2.media_id
WHERE t2.type='tag' AND t2.title IN ($arg) AND t2.playlist_id=%d
ORDER BY t1.order_id";
UPDATE: You've raised two "new" question in the comment: From your use-cases I don't see any reason for using a join here.
1: retrieve rows from media_table that have ALL required title(s) from taxonomy_table
From my point of view there is no simple solution with just using SQL (except maybe really hacky string-operations in SQL). Easiest solution might be something like this:
$countTitles = count(explode(",", $args))
$query = "SELECT media_id from {$media_table} WHERE $countTitles = (
SELECT count(media_id) from {$taxonomy_table} WHERE type='tag' AND title IN ($arg) AND playlist_id=%d
)"
2: retrieve rows from media_table that ANY required title(s) from taxonomy_table.
This is just a simple in-clause.
$query = "SELECT * FROM {$media_table}
WHERE media_id IN (
SELECT media_id FROM {$taxonomy_table} WHERE type='tag' AND title IN ($arg) AND playlist_id=%d
)
";
Upvotes: 2
Reputation: 33
use a union instead of join with a nested / join query
$query = "SELECT * FROM {$media_table}
INNER JOIN {$taxonomy_table}
ON {$media_table}.id = {$taxonomy_table}.media_id
WHERE {$taxonomy_table}.type='tag' AND {$taxonomy_table}.title IN ($arg) AND {$taxonomy_table}.playlist_id=%d
ORDER BY {$media_table}.order_id
union SELECT * FROM {$media_table}
WHERE media_id IN (
SELECT media_id FROM {$taxonomy_table} WHERE type='tag' AND title IN ($arg) AND playlist_id=%d
)
";
Upvotes: 0