Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL中的国家邻接建模_Sql_Mysql_Graph - Fatal编程技术网

SQL中的国家邻接建模

SQL中的国家邻接建模,sql,mysql,graph,Sql,Mysql,Graph,我试图在MySQL中模拟哪些国家彼此接壤。我有三张桌子: nodes ----- node_id MEDIUMINT countries --------- country_id MEDIUMINT (used as a foreign key for nodes.node_id) country CHAR(64) iso_code CHAR(2) node_adjacency -------------- node_id_1 MEDIUMINT (used as a foreign key

我试图在MySQL中模拟哪些国家彼此接壤。我有三张桌子:

nodes
-----
node_id MEDIUMINT

countries
---------
country_id MEDIUMINT (used as a foreign key for nodes.node_id)
country CHAR(64)
iso_code CHAR(2)

node_adjacency
--------------
node_id_1 MEDIUMINT (used as a foreign key for nodes.node_id)
node_id_2 MEDIUMINT (used as a foreign key for nodes.node_id)
我理解节点表在本例中是冗余的,但这是更大体系结构的一部分,其中节点可以表示国家以外的许多其他项目

以下是一些数据(ID(出现在所有三个表中)和国家/地区)

克罗地亚与所有其他国家接壤,这在node_邻接表中表示为:

59  86
86  130
86  178
86  227
86  232
因此,塞尔维亚的ID可能显示为
节点ID\u 1
节点ID\u 2
。此表中的数据基本上是无向图数据

问题:

如果名称为“克罗地亚”,我应该使用什么SQL来检索它的邻居

Bosnia and Herzegovina
Hungary
Montenegro
Serbia
Slovenia
将邻接信息存储为有向图数据会提高检索效率吗?例如,克罗地亚与匈牙利接壤,匈牙利与克罗地亚接壤,基本上重复了关系的存储:

86  130
130 86

我将存储这两个关系(匈牙利与克罗地亚接壤,克罗地亚与匈牙利接壤),这样您就只需要查询一列

SELECT c.country FROM countries AS c 
INNER JOIN node_adjacency AS n 
ON n.node_id_1 = c.countryID
WHERE c.countryID = 86

如果您要复制关系(即A国与B国共享边界,B国与A国共享边界),您可以通过简单的选择找到一种方法。如果每对国家/地区只存储一个关系,则需要在node_邻接表中按两列进行搜索(运行两个select语句并执行并集)。

要同时执行两列,只需将两个查询并集(借用Matthew Jones):


如果这样做,您将复制查询而不是数据(使用的空间减少50%),而且仍然非常简单。

这只是我的想法,所以我不知道这是否是最有效的解决方案,可能需要进行调整,但我认为它应该可以工作:

SELECT
     BORDER.country
FROM
     Countries AS C
LEFT OUTER JOIN Node_Adjacency NA1 ON
     NA1.node_id_1 = C.country_id OR
     NA1.node_id_2 = C.country_id
INNER JOIN Countries AS BORDER ON
     (
     BORDER.country_id = NA1.node_id_1 OR
     BORDER.country_id = NA1.node_id_2
     ) AND
     BORDER.country_id <> C.country_id
 WHERE
     C.country = 'CROATIA'        
选择
边境
从…起
C类国家
左外连接节点_邻接NA1 ON
NA1.node_id_1=C.country_id或
NA1.node_id_2=C.country_id
以内陆国家为边界
(
BORDER.country\u id=NA1.node\u id\u 1或
BORDER.country\u id=NA1.node\u id\u 2
)及
BORDER.country\u id C.country\u id
哪里
C.国家=‘克罗地亚’

因为你的图不是有向图,我认为把它存储为有向图是没有意义的。您可能还想在Google上搜索“Celko SQL Graph”,因为他在SQL中的树、图和层次结构方面做了大量的高级工作,并且有一本专门介绍此主题的优秀书籍。

您可以创建联合视图以避免重复:

CREATE VIEW adjacency_view (node_id_1, node_id_2)
AS
SELECT node_id_1, node_id_2 FROM node_adjacency
UNION ALL
SELECT node_id_2, node_id_1 FROM node_adjacency
因此,您的查询变得非常简单:

SELECT c1.country
FROM adjacency_view
INNER JOIN countries AS c1 on c1.country_id = adjacency_view.node_id_1
INNER JOIN countries AS c2 on c2.country_id = adjacency_view.node_id_2
WHERE c2.country = 'CROATIA'

我已经走了这么远,但如果我只有“克罗地亚”这个词,而不是86,它还能做到吗?是的;只需更改WHERE子句。已经有了用于Smarties、Tree和Hierarchies的SQL,但不幸的是,Celko的许多写作超出了我的理解。谢谢你的解决方案!
CREATE VIEW adjacency_view (node_id_1, node_id_2)
AS
SELECT node_id_1, node_id_2 FROM node_adjacency
UNION ALL
SELECT node_id_2, node_id_1 FROM node_adjacency
SELECT c1.country
FROM adjacency_view
INNER JOIN countries AS c1 on c1.country_id = adjacency_view.node_id_1
INNER JOIN countries AS c2 on c2.country_id = adjacency_view.node_id_2
WHERE c2.country = 'CROATIA'