我有一个名为'countries'的表格链接到另一个表'网络',有多对多关系:
countries countries_networks networks
+-------------+----------+ +-------------+----------+ +-------------+---------------+
| Field | Type | | Field | Type | | Field | Type |
+-------------+----------+ +-------------+----------+ +-------------+---------------+
| id | int(11) | | id | int(11) | | id | int(11) |
| countryName | char(35) | | country_id | int(11) | | name | varchar(100) |
+-------------+----------+ | network_id | int(11) | | description | varchar(255) |
检索network_id为6&的所有国家/地区。 7,我只是执行以下操作:(我可以进一步使用networks.name但我知道countries_networks.network_id所以我只是使用它们来减少SQL。)
SELECT DISTINCT countryName
FROM countries AS Country
INNER JOIN countries_networks AS n ON Country.id = n.country_id
WHERE n.network_id IN (6,7)
这很好,但我想要检索网络数量为8的国家,而不是其他国家。
我尝试了以下但是仍在使用6& 7英寸。这与我的JOIN有关吗?
SELECT DISTINCT countryName
FROM countries AS Country
INNER JOIN countries_networks AS n ON Country.id = n.country_id
WHERE n.network_id IN (8)
AND n.network_id not IN(6,7)
感谢。
答案 0 :(得分:2)
您需要两个联接:
SELECT DISTINCT c.CountryName
FROM Countries c
INNER JOIN
countries_networks n
ON c.id = n.country_id
AND n.network_id = 8
LEFT JOIN
countries_networks n2
ON c.id = n2.country_id
AND n2.network_id IN (6, 7)
WHERE n2.country_id IS NULL
正如你的查询中所说的那样,你所检查的最后一行是8不在列表中(6,7)。如果我正确地阅读了您的问题,您希望国家/地区拥有ID为8的网络但没有ID为6或7的网络。每个网络都需要自己的连接,并且您希望确保没有匹配第二行。
答案 1 :(得分:2)
使用NOT EXISTS谓词的另一个解决方案。
SELECT DISTINCT countryName
FROM countries AS Country
INNER JOIN countries_networks AS n ON Country.id = n.country_id
WHERE n.network_id IN (8)
AND NOT EXISTS (SELECT 1 FROM countries_networks n1
WHERE n1.country_id = Country.id AND n1.network_id !=8)
答案 2 :(得分:1)
SELECT countryName
FROM countries
WHERE country_id IN
(
SELECT country_id
FROM network
WHERE network_id = 8
)
AND country_id NOT IN
(
SELECT country_id
FROM network
WHERE network_id IN (6, 7)
)
答案 3 :(得分:0)
你可以做一个子查询:
SELECT DISTINCT c.countryName
FROM countries AS c
INNER JOIN countries_networks AS n ON c.id = n.country_id
WHERE n.network_id IN (8)
AND c.countryName NOT IN
(SELECT c2.countryName FROM countries AS c2
INNER JOIN countries_networks AS n2
WHERE n2.network_id IN (6,7))
虽然这可能不是最佳的。
答案 4 :(得分:0)
您获得网络ID为6和7的国家/地区的原因是您要检查每个countries_networks记录的条件。排除6和7的条件部分完全没有效果,因为任何8的id永远不能同时为6或7。
您需要两次加入countries_networks表格,以便您可以使用一个国家/地区和一个国家/地区来排除国家/地区:
select countryName
from countries c
inner join countries_networks i on i.country_id = c.id and i.network_id = 8
left join countries_networks e on e.country_id = c.id and e.network_id in (6,7)
where e.id is null
此外,除非实际上在同一个国家/地区和网络ID之间存在多个连接,否则您不需要区分此查询。
答案 5 :(得分:0)
虽然您在networks
表上拒绝其他联接,但这确实是最简单的方法。如果您针对该表测试您的ID,则应适当限制您的结果:
SELECT countryName
FROM countries AS Country JOIN countries_networks AS cn
ON Country.id = cn.country_id
JOIN networks n
ON cn.network_id = n.id
WHERE n.network_id IN (8)
针对networks
表的测试应该限制结果,而不考虑countries_networks
表中可能链接的任何内容。它还应该比子查询或我能想到的任何其他解决方案更好地执行(和读取)。