mysql - 查询查找被另一个国家隔开的所有国家对

标签 mysql sql database

提前感谢您的宝贵时间

我有来自 mondial 数据库的下表(WebsiteDocumentation)。

CREATE TABLE borders
(Country1 VARCHAR(4),
 Country2 VARCHAR(4),
 Length FLOAT, 
 CONSTRAINT CHECK (Length > 0),
 CONSTRAINT BorderKey PRIMARY KEY (Country1,Country2));

该表不包含倒数值(它只包含Country1, Country2Country2, 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, RSMRSM, F存在)像上面提到的那样,我也认为我开发的查询真的很糟糕,因为它一遍又一遍地重复相同的查询。我已经搜索了避免这种情况的方法,并且找到了一些有趣的解决方案,例如 WITH tmp AS query 子句,但是我正在使用 MySQLWITH AS 子句。

那么专家们怎么看?这至少是正确的方法吗?我是否遗漏了一些明显的东西?

提前感谢您的宝贵时间,如果这个糟糕的查询让您头疼,我们深表歉意。

编辑 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/

相关文章:

java - homeandlearn 数据库教程 - rs.Next 空指针异常

mysql - 给出用户的总订单价格,不重复

mysql - 存储过程中不允许加载数据

mysql - 如何将多行数据分组到同一行?

mysql - 将 MySql 数据库中的所有日期增加指定的天数

mysql - 创建具有相对日期的 MYSQL 查询

sql - SELECT 中的上限字段值

mysql - mySQL 中的奇怪 Ascii 字符。需要查询才能删除

php - SQLSTATE[HY093] : Invalid parameter number: mixed named and positional parameters

sql - 在SQL Server中, "SET ANSI_NULLS ON"是什么意思?