我有一組與標記集具有多對多關係的城市。用戶爲我提供了一組標籤(,其中可能包含重複項!),我需要返回匹配條目的列表,按相關性排序。通過多個標記進行相關排序搜索的SQL查詢
數據
下面是一些樣本數據來說明問題:
城市:
--------------------
| id | city |
--------------------
| 1 | Atlanta |
| 2 | Baltimore |
| 3 | Cleveland |
| 4 | Denver |
| 5 | Eugene |
--------------------
標籤:
------
| id |
------
| 1 |
| 2 |
| 3 |
| 4 |
------
這些城市的標籤是這樣的:
Atlanta: 1, 2
Baltimore: 3
Cleveland: 1, 3, 4
Denver: 2, 3
Eugene: 1, 4
...所以CityTags表如下所示:
------------------------
| city_id | tag_id |
------------------------
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 3 |
| 3 | 4 |
| 4 | 2 |
| 4 | 3 |
| 5 | 1 |
| 5 | 4 |
------------------------
例1
如果用戶給我的標籤ID:1,3,3,4],我想算我有多少場比賽對每個標籤,並返回像相關性排序的結果:
------------------------
| city | matches |
------------------------
| Cleveland | 4 |
| Baltimore | 2 |
| Eugene | 2 |
| Atlanta | 1 |
| Denver | 1 |
------------------------
由於克利夫蘭匹配所有四個標籤,它是第一,其次是巴爾的摩和尤金,每個有兩個標籤匹配,等等
示例2
另一個用於衡量的例子。對於搜索[2,2,2,3,4],我們會得到:
------------------------
| city | matches |
------------------------
| Denver | 4 |
| Atlanta | 3 |
| Cleveland | 2 |
| Baltimore | 1 |
| Eugene | 1 |
------------------------
SQL
如果我忽略重複的標籤,那麼它的瑣碎:
SELECT name,COUNT(name) AS relevance FROM
(SELECT name FROM cities,citytags
WHERE id=city_id AND tag_id IN (1,3,3,4)) AS matches
GROUP BY name ORDER BY relevance DESC;
但那不是我需要的。我需要尊重重複。有人可以建議我怎麼做到這一點?
Postgresql中的解決方案
啊哈!臨時表是我需要的。 Postgresql讓我用它的WITH語法來做到這一點。這裏的解決方案:
WITH search(tag) AS (VALUES (1), (3), (3), (4))
SELECT name, COUNT(name) AS relevance FROM cities
INNER JOIN citytags ON cities.id=citytags.city_id
INNER JOIN search ON citytags.tag_id=search.tag
GROUP BY name ORDER BY relevance DESC;
非常感謝那些回答。
用戶如何輸入標籤列表?他們是否鍵入一個逗號分隔的列表,然後將它們連接到查詢中? – mellamokb