提前感谢您的宝贵时间
我有来自 mondial 数据库的下表(Website,Documentation)。
CREATE TABLE borders
(Country1 VARCHAR(4),
Country2 VARCHAR(4),
Length FLOAT,
CONSTRAINT CHECK (Length > 0),
CONSTRAINT BorderKey PRIMARY KEY (Country1,Country2));
该表不包含倒数值(它只包含Country1, Country2 或Country2, Country1 来定义边界)。
我需要查询输出所有非邻国但邻国的国家对(所有被另一个国家隔开的国家对)。
Country1 和 Country2 包含国家代码,例如“F”代表法国,“I”代表意大利等。这是输出的示例行:
RSM || F
RSM 是圣马力诺共和国的代号(圣马力诺是一个完全被意大利包围的飞地)。 RSM 显然不是法国的邻居,但意大利是,所以输出包含 RSM, F 对,它还包含所有其他邻国的相似对去意大利。
我花了几个小时试图找出解决方案,但我离找到解决方案还很远,而且我已经有很多问题,这就是我所做的:
我首先进行查询以找出某个国家/地区的所有邻居。
SELECT Country1
FROM borders
WHERE Country2 = "RSM"
UNION
SELECT Country2
FROM borders
WHERE Country1 = "RSM"
这显然只输出“I”,这是意大利的代码(所以它是正确的)。我已经有一个问题:是否有更好的方法来做到这一点,或者这样可以吗?
然后我将它带到下一步并查询以找到以前找到的邻居的所有邻居:
SELECT Country1
FROM borders
WHERE Country2 IN (
SELECT Country1
FROM borders
WHERE Country2 = "RSM"
UNION
SELECT Country2
FROM borders
WHERE Country1 = "RSM"
)
UNION
SELECT Country2
FROM borders
WHERE Country1 IN (
SELECT Country1
FROM borders
WHERE Country2 = "RSM"
UNION
SELECT Country2
FROM borders
WHERE Country1 = "RSM"
)
所以我基本上做同样的事情,但不是寻找特定国家/地区的邻国,而是搜索特定国家/地区组的所有邻国。查询未完成,因为我需要从输出中删除起始国家及其所有邻国,因此查询变为:
SELECT "RSM", Country1
FROM (
SELECT Country1
FROM borders
WHERE Country2 IN (
SELECT Country1
FROM borders
WHERE Country2 = "RSM"
UNION
SELECT Country2
FROM borders
WHERE Country1 = "RSM"
)
UNION
SELECT Country2
FROM borders
WHERE Country1 IN (
SELECT Country1
FROM borders
WHERE Country2 = "RSM"
UNION
SELECT Country2
FROM borders
WHERE Country1 = "RSM"
)
) tmp
WHERE tmp.Country1 NOT IN (
SELECT Country1
FROM borders
WHERE Country2 = "RSM"
UNION
SELECT Country2
FROM borders
WHERE Country1 = "RSM"
) AND tmp.Country1 != "RSM"
此查询适用于单个起始国家 (RSM),但我需要输出所有不同的(意味着输出中没有 F, RSM 对 RSM, F存在)像上面提到的那样,我也认为我开发的查询真的很糟糕,因为它一遍又一遍地重复相同的查询。我已经搜索了避免这种情况的方法,并且找到了一些有趣的解决方案,例如 WITH tmp AS query 子句,但是我正在使用 MySQL 和 WITH AS不支持 em> 子句。
那么专家们怎么看?这至少是正确的方法吗?我是否遗漏了一些明显的东西?
提前感谢您的宝贵时间,如果这个糟糕的查询让您头疼,我们深表歉意。
编辑 1:我做了一个 SQL Fiddle包含表、数据和我的查询,以防您希望能够轻松运行查询。我希望它会对某人有所帮助。
最佳答案
用户 jpw在评论中解决了问题。
很多用户建议做一个表格 View ,这样可以使夫妻或国家对称:
CREATE VIEW borders_symmetrical AS
SELECT Country1, Country2 FROM borders
UNION ALL
SELECT Country2, Country1 FROM borders;
在我看来,这确实是一个很好的建议,它展示了 View 如何真正有用。现在查询变得容易多了:
SELECT DISTINCT b1.Country1, b2.Country2
FROM borders_symmetrical b2
JOIN borders_symmetrical b1
ON b2.Country1 = b1.Country2
WHERE b2.Country2 <> b1.Country1
#AND (b1.Country1 = 'RSM' OR b2.Country2 = 'RSM') # Debug a single nation
AND b2.country2 NOT IN (
SELECT Country2
FROM borders_symmetrical
WHERE Country1 = b1.Country1
) AND b1.Country1 < b2.Country2
我重新发布了这个,因为 jpw 没有提交和回答,只是评论了帖子。
再次感谢大家抽出宝贵的时间,你们帮了我很多,让我了解了一些关于 SQL 和数据库的重要知识。
关于mysql - 查询查找被另一个国家隔开的所有国家对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31963941/