簡體   English   中英

在MySQL中選擇多對多關系

[英]Select in a many-to-many relationship in MySQL

我在MySQL數據庫中有兩個表,Locations和Tags,以及第三個表LocationsTagsAssoc,它們將兩個表關聯起來並將它們視為多對多關系。

表結構如下:

Locations
---------
ID int (Primary Key)
Name varchar(128)

LocationsTagsAssoc
------------------
ID int (Primary Key)
LocationID int (Foreign Key)
TagID int (Foreign Key)

Tags
----
ID int (Primary Key)
Name varchar(128)

因此,每個位置都可以使用多個標記字進行標記,並且每個標記字都可以標記為多個位置。

我想要做的是只選擇標有所有提供的標簽名稱的位置 例如:

我想要所有標有“樹”和“秋千”的地點。 應選擇位置“公園”,但不應選擇位置“森林”。

任何見解將不勝感激。 謝謝!

有兩種方法可以做到這一點。 我更喜歡第一種方式,即為每個標簽自我加入:

SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a1 ON a1.LocationID = l.ID
JOIN Tags t1 ON a1.TagID = t1.ID AND t1.Name = ?
JOIN LocationsTagsAssoc a2 ON a2.LocationID = l.ID
JOIN Tags t2 ON a2.TagID = t2.ID AND t2.Name = ?
JOIN LocationsTagsAssoc a3 ON a3.LocationID = l.ID
JOIN Tags t3 ON a3.TagID = t3.ID AND t3.Name = ?;

另一種方式也有效,但在MySQL中使用GROUP BY往往會產生臨時表並且性能很慢:

SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a ON a.LocationID = l.ID
JOIN Tags t ON a.TagID = t.ID
WHERE t.Name IN (?, ?, ?)
GROUP BY l.ID
HAVING COUNT(*) = 3;

您需要的位置不存在LocationsTagsAssoc表中未顯示給定標記的位置。

您可以使用IN()指定給定標記,如下所示,或者通過連接到包含它們的另一個表。

SELECT l.*
FROM Locations AS l
WHERE NOT EXISTS (
    SELECT NULL FROM Tags AS t
    WHERE NOT EXISTS (
        SELECT NULL FROM LocationsTagsAssoc AS lt
        WHERE lt.LocationId = l.ID
            AND lt.TagID = t.ID
    )
        AND t.ID IN (1, 2, 3,...)
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM