查询在数据库中具有公共标记的位置

时间:2012-02-09 21:19:50

标签: sql database sqlite

我有一个SQLIte数据库,其中包含用于标记的位置和表的表,

CREATE TABLE places (
    id INTEGER NOT NULL, 
    name VARCHAR(256), 
    address VARCHAR(256),
    PRIMARY KEY (id)
)

CREATE TABLE tags (
    id INTEGER NOT NULL, 
    name VARCHAR(256) NOT NULL, 
    PRIMARY KEY (id)
)

我还有第三个表来映射前两个之间的关联,

CREATE TABLE placestags (
    id INTEGER NOT NULL, 
    placeid INTEGER, 
    tagid INTEGER, 
    PRIMARY KEY (id), 
    FOREIGN KEY(placeid) REFERENCES places (id), 
    FOREIGN KEY(tagid) REFERENCES tags (id)
)

我可以使用以下命令

获取哪些地方标记了哪些标签
SELECT places.id, places.name, tags.id, tags.name
FROM (placestags INNER JOIN places on placestags.placeid = places.id
           INNER JOIN tags on tags.id = placestags.tagid)
WHERE placestags.tagid=tags.id

将返回这样的内容,

id | name          | id | name
---------------------------------          
1  | McDonalds     | 1  | Burgers
2  | Pizza Hut     | 2  | Pizza
3  | Burger King   | 1  | Burgers

我想知道是否可以构造一个查询,以便返回共享两个或多个标签的地点的名称。例如,如果McDonaldsBurger King共享标记BurgersFries,那么我想将此列出,

p1id | p1name      | p2id | p2name      | t1id | t1name        | t2id | t2name
--------------------------------------------------------------------------------          
1    | McDonalds   | 3    | Burger King | 1    | Burgers       | 3    | Fries

这可以用SQL吗?

2 个答案:

答案 0 :(得分:2)

您可以使用此查询生成以下结果:

select p1.name, p2.name, t.name
from places p1
join placestags pt1 on p1.id=pt1.placeid
join placestags pt2 on pt1.tagid=pt2.tagid and pt2.placeid <> p1.id
join places p2 on pt2.placeid=p2.id
join tags t on t.id=pt1.tagid
order by p1.id, t.id

这并没有像你想要的那样将所有内容整合到一行中(你需要一个支点,而我认为sqlite没有它),但它可以让你看到发生了什么。以下是您从此查询中获得的内容:

Place1      |   Place2       | Shared_Tag
------------|----------------|-----------
McDonalds       Burger King     Burgers
McDonalds       Burger King     Fries
Burger King     McDonalds       Burgers
Burger King     McDonalds       Fries

编辑(回复评论):

如果您希望缩短查询时间,请尝试减少连接数,并删除对称重复项,如下所示:

select pt1.placeid, pt2.placeid, pt1.tagid
from placestags pt1
join placestags pt2 on pt1.tagid=pt2.tagid and pt2.placeid > pt1.placeid
order by pt1.placeid, pt1.tagid

答案 1 :(得分:1)

这并不能解决“查找相关性”问题,但是因为你也有点要求......

sqlite支持交叉,因此您可以执行以下操作。如果我们知道两个标签,我们可以找到我们想要的标签的交叉点。它不漂亮,可能不是长期的东西,但如果你只是试图了解你的数据,它可能会有所帮助。

假设我们有两个id为1&amp;的标签。 2:

SELECT places.name FROM places 
  INNER JOIN placestags ON places.id=placestags.placeid 
  WHERE placestags.tagid = 1 
INTERSECT 
SELECT places.name FROM places 
  INNER JOIN placestags ON places.id=placestags.placeid 
  WHERE placestags.tagid = 2;