我在php中用餐馆搜索有两张桌子。关于餐厅类型,设施,美食的所有信息都参考表2中的餐馆ID进入表2中。我如何运行查询以便我可以获得所有服务于餐馆的餐厅。供应晚餐,还有停车位吗?
这似乎不起作用:
SELECT DISTINCT restaurant.name, restaurant.place
FROM stack,restaurant
WHERE restaurant.id=stack.rest_id AND stack.value='chineese'
AND stack.value='dinner' AND stack.value='parking'
这是我的表结构
Table1 - **restaurant**
------+----------+----------
id + name + place
------+----------+----------
1 rest1 ny
2 rest2 la
3 rest3 ph
4 rest4 mlp
Table2 - **stack**
------+----------+-------------------------
id + rest_id + type + value
------+----------+-------------------------
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
还告诉我这是不是错误的方法。我使用堆栈,因为美食,设施都可以是无限的,因为它没有定义,非常适合每个人。
答案 0 :(得分:1)
我知道做这样的事情的唯一方法是“转动”数据 - 基本上将行放入列中。例如。您目前每个值都有1行,但理想情况下,您希望每个餐厅都有1行,以便查询值。
坏消息是你需要知道select语句中的所有可能值,否则你需要使用游标。
以下内容应该介绍如何创建数据透视表:
SELECT
rest_id,
MAX(CASE WHEN s.value = 'chinese' THEN 1 ELSE 0 END) AS chinese,
MAX(CASE WHEN s.value = 'breakfast' THEN 1 ELSE 0 END) AS breakfast,
MAX(CASE WHEN s.value = 'party hall' THEN 1 ELSE 0 END) AS [party hall],
MAX(CASE WHEN s.value = 'lunch' THEN 1 ELSE 0 END) AS lunch,
MAX(CASE WHEN s.value = 'dinner' THEN 1 ELSE 0 END) AS dinner,
MAX(CASE WHEN s.value = 'seafood' THEN 1 ELSE 0 END) AS seafood,
MAX(CASE WHEN s.value = 'Italian' THEN 1 ELSE 0 END) AS Italian,
MAX(CASE WHEN s.value = 'parking' THEN 1 ELSE 0 END) AS parking,
MAX(CASE WHEN s.value = 'Indian' THEN 1 ELSE 0 END) AS indian
FROM
stack AS s
GROUP BY
rest_id
这将创建一个如下表格:
rest_id | chinese | breakfast | party hall | lunch | dinner | seafood | Italian | parking | indian
--------+---------+-----------+------------+-------+--------+---------+---------+---------+-------
1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0
2 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1
从这张桌子开始,这是一个非常简单的连接,以获得具有特定功能的餐厅。
例如:
SELECT restaurant.name, restaurant.place FROM restaurant LEFT JOIN
(SELECT
rest_id,
MAX(CASE WHEN s.value = 'chinese' THEN 1 ELSE 0 END) AS chinese,
MAX(CASE WHEN s.value = 'breakfast' THEN 1 ELSE 0 END) AS breakfast,
MAX(CASE WHEN s.value = 'party hall' THEN 1 ELSE 0 END) AS [party hall],
MAX(CASE WHEN s.value = 'lunch' THEN 1 ELSE 0 END) AS lunch,
MAX(CASE WHEN s.value = 'dinner' THEN 1 ELSE 0 END) AS dinner,
MAX(CASE WHEN s.value = 'seafood' THEN 1 ELSE 0 END) AS seafood,
MAX(CASE WHEN s.value = 'Italian' THEN 1 ELSE 0 END) AS Italian,
MAX(CASE WHEN s.value = 'parking' THEN 1 ELSE 0 END) AS parking,
MAX(CASE WHEN s.value = 'Indian' THEN 1 ELSE 0 END) AS indian
FROM
stack AS s
GROUP BY
rest_id) AS features
ON
restaurant.id=features.rest_id
WHERE
features.chinese=1 and features.dinner=1 and features.parking=1
答案 1 :(得分:1)
鉴于您现有的结构,这很容易:
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);
答案 2 :(得分:0)
试试这个..
SELECT r.name FROM restaurant as r JOIN stack as s ON r.id = s.rest_id WHERE s.value ='chinese'AND s.value ='dinner'AND s.value ='parking';