在两个表之间查询数据的最佳方法是什么?这两个表没有直接关联,而是通过第三个甚至第四个表,使用外键相关?
类似于1 -> 2 -> 3 -> 4
。
我看到了许多非常不同的建议,但是想了解在这种情况下最好的方法,我尝试维护关系数据库模型,同时避免超级复杂的SQL查询。
以下示例符合我的情况:
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`city_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_city_id` FOREIGN KEY (`city_id`)
REFERENCES `city` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
CREATE TABLE `city` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`country_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_country_id` FOREIGN KEY (`country_id`)
REFERENCES `country` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
CREATE TABLE `country` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`continent_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_continent_id` FOREIGN KEY (`continent_id`)
REFERENCES `continent` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
CREATE TABLE `continent` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
让我们说我想让所有用户来自特定的大陆
SELECT name FROM user WHERE city_id IN (
SELECT id FROM city WHERE country_id IN (
SELECT id FROM country WHERE continent_id = 1 ) ) );
我认为看起来不错,但如果我想让特定城市的所有用户
,该怎么办?SELECT name FROM user WHERE city_id IN (
SELECT id FROM city WHERE country_id IN (
SELECT id FROM country WHERE continent_id = (
SELECT continent_id FROM country WHERE id = (
SELECT country_id FROM city WHERE id = 1 ) ) ) );
效率这么高吗?
也许可以通过JOIN实现相同的目标吗?
我试图避免将所有值添加到用户表,以维持该关系city->country->continent
并让关系完成工作,但也许在这种情况下,它不值得这样做? ..可能效率不高,重新设计数据库会更好吗?
答案 0 :(得分:1)
内部联接
-- get users to cities
from
City c
inner join Users u
on c.Id = u.City_Id
-- users to continents
from
Users u
inner join City ci
on u.City_id = ci.Id
inner join Country co
on ci.Country_Id = co.Id
inner join Continent con
on co.Continent_Id = con.Id
答案 1 :(得分:1)
应该是这样的,你可能想分析(解释为什么JOIN比子查询更好)EXPLAIN手册页http://dev.mysql.com/doc/refman/5.7/en/explain.html
请注意,您只能通过LEFT JOIN或RIGHT JOIN使用下面的过滤器信任INNER JOIN,您可能会得到错误的结果..
适用于continent_id = 1
的大陆内的所有用户SELECT
user.name
FROM
user
INNER JOIN
city
ON
user.city_id = city.id
INNER JOIN
country
ON
city.country_id = country.id
AND
country.continent_id = 1
;
适用于city_id = 1
的城市内的所有用户SELECT
user.name
FROM
user
INNER JOIN
city
ON
user.city_id = city.id
AND
city.id = 1