Reputation: 495
I am trying to get each item, and their respective tags with one query given a user_id.
CREATE TABLE IF NOT EXISTS `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`description` mediumtext NOT NULL,
`user_id` bigint(100) NOT NULL,
`to_read` tinyint(1) NOT NULL DEFAULT '0',
`added_at` datetime NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(100) NOT NULL,
`item_id` int(11) NOT NULL,
`tag` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `item_id` (`item_id`),
KEY `user_id` (`user_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query:
SELECT tags.tag FROM tags WHERE tags.item_id = 5;
SELECT tag FROM tags t JOIN items item ON t.item_id = item.id AND t.item_id = 5;
Which of my queries is correct to retrieve each items TAGS!
Upvotes: 0
Views: 74
Reputation: 18034
If you only want to get the tags, use
SELECT tag FROM tags WHERE item_id = 42;
To get the item AND the tags you need "Left outer join". Otherwise, items with no tags will be ignored:
SELECT tag FROM tags t LEFT JOIN items item ON t.item_id = item.id AND t.item_id = 42;
Note, however, that might get the same tag multiple times. To avoid this, use SELECT DISTINCT ...
instead.
Edit: The following statement returns one row per item, with an additional column that concatenates all tags of that item:
SELECT items.*,
(SELECT GROUP_CONCAT(tags.tag)
FROM tags
WHERE tags.item_id = items.id) AS tags
FROM items WHERE items.user_id = 0;
In case that you decide to switch to a three-table layout with a tags_items
table:
SELECT items.*,
(SELECT GROUP_CONCAT(tags.tag) FROM tags
WHERE tags.id = tags_items.tag_id) AS tags
FROM items
LEFT JOIN tags_items
ON tags_items.item_id = items.id
WHERE items.user_id = 0;
Upvotes: 1