感谢您的时间。
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),但我需要输出所有不同的夫妻组合(意思是,如果输出中存在RSM,F,则没有F,RSM),如上所述,而且我认为我编写的查询非常糟糕,因为它一遍又一遍地重复相同的查询。我已经搜索了避免这种情况的方法,并找到了一些有趣的解决方案,例如WITH tmp AS query子句,但我正在使用MySQL,不支持WITH AS子句。
那么你们专家认为呢?这至少接近正确的方式吗?我错过了一些明显的东西吗?
提前感谢您的时间,如果这个可怕的查询给您带来了头痛,对不起。
编辑1:我制作了一个SQL Fiddle,其中包含表格、数据和我的查询,以便您可以轻松运行查询。我希望它能对某人有所帮助。