Учитывая вашу существующую структуру, это довольно легко:
SELECT name, place FROM restaurant WHERE id IN (
SELECT rest_id FROM stack
WHERE value IN ('chinese', 'dinner', 'parking')
GROUP BY rest_id
HAVING COUNT(rest_id)=3);
Просто убедитесь, что числовое значение дано HAVING COUNT(rest_id)
совпадает с числом значений, которые вы искали , Вот простой тест (обратите внимание, что я добавил еще один ресторан, который на самом деле имеет «китайский», «ужин» и «парковка»:
CREATE TABLE `restaurant` (
`id` int(11) NOT NULL auto_increment,
`name` VARCHAR(255),
`place` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `stack` (
`id` int(11) NOT NULL auto_increment,
`rest_id` int(11) NOT NULL,
`type` VARCHAR(255),
`value` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
INSERT INTO `restaurant` VALUES
(1, 'rest1', 'ny'),
(2, 'rest2', 'la'),
(3, 'rest3', 'ph'),
(4, 'rest4', 'mlp');
INSERT INTO `stack` VALUES
(1, 1, 'cuisine', 'chinese'),
(2, 1, 'serves', 'breakfast'),
(3, 1, 'facilities', 'party hall'),
(4, 1, 'serves', 'lunch'),
(5, 1, 'serves', 'dinner'),
(6, 1, 'cuisine', 'seafood'),
(7, 2, 'cuisine', 'Italian'),
(8, 2, 'serves', 'breakfast'),
(9, 2, 'facilities', 'parking'),
(10, 2, 'serves', 'lunch'),
(11, 2, 'serves', 'dinner'),
(12, 2, 'cuisine', 'indian'),
(13, 3, 'cuisine', 'chinese'),
(14, 3, 'serves', 'breakfast'),
(15, 3, 'facilities', 'parking'),
(16, 3, 'serves', 'lunch'),
(17, 3, 'serves', 'dinner'),
(18, 3, 'cuisine', 'indian');
SELECT name, place FROM restaurant WHERE id IN (
SELECT rest_id FROM stack
WHERE value IN ('chinese', 'dinner', 'parking')
GROUP BY rest_id
HAVING COUNT(rest_id)=3);
+-------+-------+
| name | place |
+-------+-------+
| rest3 | ph |
+-------+-------+
SELECT name, place FROM restaurant WHERE id IN (
SELECT rest_id FROM stack
WHERE value IN ('chinese', 'dinner')
GROUP BY rest_id
HAVING COUNT(rest_id)=2);
+-------+-------+
| name | place |
+-------+-------+
| rest1 | ny |
| rest3 | ph |
+-------+-------+
SELECT name, place FROM restaurant WHERE id IN (
SELECT rest_id FROM stack
WHERE value IN ('parking', 'hellipad')
GROUP BY rest_id
HAVING COUNT(rest_id)=2);
Empty set (0.00 sec)
В качестве альтернативы, вы можете создать связанные таблицы, как это (но это вероятно, не лучшая структура):
---> facility
restaurant ---> restaurant_has_facility ---|
---> facility_type
запрос почти то же самое, вы просто нужна ваша подзапрос, чтобы произвести соответствующую присоединиться:
SELECT restaurant_name, restaurant_place FROM (
SELECT
r.id AS restaurant_id,
r.name AS restaurant_name,
r.place AS restaurant_place,
ft.name AS facility_name
FROM restaurant AS r
JOIN restaurant_has_facility AS rf ON rf.restaurant_id = r.id
JOIN facility_type AS ft ON ft.id = rf.facility_type_id
ORDER BY r.id, ft.name) AS tmp
WHERE facility_name IN ('chinese', 'dinner', 'parking')
GROUP BY tmp.restaurant_id
HAVING COUNT(tmp.restaurant_id)=3;
Вот некоторые примеры SQL для выше Структура:
CREATE TABLE `restaurant` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NOT NULL ,
`place` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE `facility` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `facility_type` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `restaurant_has_facility` (
`restaurant_id` INT UNSIGNED NOT NULL ,
`facility_id` INT UNSIGNED NOT NULL ,
`facility_type_id` INT UNSIGNED NOT NULL ,
PRIMARY KEY (`restaurant_id`, `facility_id`, `facility_type_id`) ,
INDEX `fk_restaurant_has_facility_restaurant` (`restaurant_id` ASC) ,
CONSTRAINT `fk_restaurant_has_facility_restaurant`
FOREIGN KEY (`restaurant_id`)
REFERENCES `restaurant` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
INSERT INTO `restaurant` VALUES
(1, 'rest1', 'ny'),
(2, 'rest2', 'la'),
(3, 'rest3', 'ph'),
(4, 'rest4', 'mlp');
INSERT INTO `facility` VALUES
(1, 'cuisine'),
(2, 'serves'),
(3, 'facilities');
INSERT INTO `facility_type` VALUES
(1, 'chinese'),
(2, 'breakfast'),
(3, 'party hall'),
(4, 'lunch'),
(5, 'dinner'),
(6, 'seafood'),
(7, 'Italian'),
(8, 'parking'),
(9, 'indian');
INSERT INTO `restaurant_has_facility` VALUES
(1, 1, 1),
(1, 2, 2),
(1, 3, 3),
(1, 2, 4),
(1, 2, 5),
(1, 1, 6),
(2, 1, 7),
(2, 2, 2),
(2, 3, 8),
(2, 2, 4),
(2, 2, 5),
(2, 1, 9),
(3, 1, 1),
(3, 2, 5),
(3, 3, 8),
(3, 2, 4),
(3, 2, 2),
(3, 1, 9);