鉴于现有的结构,那是很容易的:
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);