[英]Modelling country adjacency in SQL
我正在嘗試建模哪些國家在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(在所有三個表格中都出現)和國家/地區)
59 Bosnia and Herzegovina
86 Croatia
130 Hungary
178 Montenegro
227 Serbia
232 Slovenia
克羅地亞與所有其他國家接壤,在node_adjacency表中表示為:
59 86
86 130
86 178
86 227
86 232
因此,塞爾維亞的ID可能顯示為node_id_1
或node_id_2
。 該表中的數據本質上是無向圖數據。
問題:
給定名稱“克羅地亞”,我應該使用什么SQL來檢索其鄰居?
Bosnia and Herzegovina
Hungary
Montenegro
Serbia
Slovenia
將鄰接信息存儲為有向圖數據時,檢索效率會有所提高嗎? 例如,克羅地亞與匈牙利接壤,匈牙利與克羅地亞接壤,從本質上來說,這種關系的存儲是重復的:
86 130
130 86
這只是我的頭上的問題,所以我不知道這是否是性能最高的解決方案,它可能需要調整,但我認為它應該可以工作:
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'
由於您的圖不是有向圖,因此我認為將其存儲為有向圖是沒有道理的。 您可能還需要Google“ Celko SQL Graph”,因為他在SQL的樹,圖和層次結構方面做了大量的高級工作,並且有一本專門介紹該主題的優秀書籍。
我將存儲兩個關系(匈牙利與克羅地亞接壤,克羅地亞與匈牙利接壤),因此您只需要查詢一列。
SELECT c.country FROM countries AS c
INNER JOIN node_adjacency AS n
ON n.node_id_1 = c.countryID
WHERE c.countryID = 86
要完成這兩個列,只需將兩個查詢合並在一起(從Matthew Jones借用):
SELECT c.country FROM countries AS c
INNER JOIN node_adjacency AS n
ON n.node_id_1 = c.countryID
WHERE c.countryID = 86
UNION
SELECT c.country FROM countries AS c
INNER JOIN node_adjacency AS n
ON n.node_id_2 = c.countryID
WHERE c.countryID = 86
如果以這種方式進行操作,則可以重復查詢而不是重復數據(節省50%的空間),而且它仍然非常簡單。
如果您正在復制關系(例如,國家A與B接壤,B與A接壤),則可以通過簡單的選擇找到一種方法。 如果每對國家/地區僅存儲一個關系,則需要按node_adjacency表中的兩列進行搜索(運行兩個select語句並執行一個並集)。
您可以創建聯合視圖以避免重復:
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'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.