SQL多个左连接

时间:2014-02-10 16:50:25

标签: mysql sql

我有一个名为文档的表,其中一行名为Nigel Harding

DOCUMENTS
id | label
24 | Nigel Harding

他已被另外两个文件标记,其中ID为1&该表称为文档标签

DOCUMENT_TAGS
id | label | Document_id
1 | TAG A | 24
12 | TAG B | 24

我正在尝试创建一个查询,我可以找到一个结果,如果搜索标签 1和12 ,Nigel Harding将出现一次,但我没有运气。

我想出了搜索一个标签ID的查询,但我正在尝试对这两个标签进行查询。

SELECT documents.id 
FROM documents 
LEFT JOIN documents_tags 
ON documents.id=documents_tags.document_id 
WHERE documents_tags.tag_id = 1 ORDER BY documents.label

我理解为什么要添加......

AND documents_tags.tag_id = 12

...到最后将无法工作,但我不知道我需要做什么让正确的查询显示我的一个结果,因为我对SQL的理解是非常基本的。

5 个答案:

答案 0 :(得分:2)

如果我理解了您的问题,那么您就缺少INDISTINCT

SELECT DISTINCT documents.id 
FROM documents 
LEFT JOIN documents_tags 
ON documents.id=documents_tags.document_id 
WHERE documents_tags.tag_id IN (1, 12) ORDER BY documents.label

使用IN,您将获得指定的任何标记ID的文档,并使用DISTINCT确保每个文档ID只能获取一次。


编辑:由于您是通过documents.label订购的,我猜这是您想要显示的内容。不要忘记您可以将SELECT声明更改为:

SELECT DISTINCT documents.label

甚至是:

SELECT DISTINCT documents.id, documents.label

答案 1 :(得分:1)

我认为解决此类问题最灵活的方法是使用带有having子句的聚合。这是一个例子:

SELECT dt.document_id 
FROM documents_tags dt
GROUP BY dt.document_id
HAVING sum(dt.tag_id = 1) > 0 and
       sum(dt.tag_id = 12) > 0;

having子句中的每个条件都会计算1(或12)的文档标记数,并且仅当找到两者时,过滤器才会通过。您也可以将其写为:

SELECT dt.document_id 
FROM documents_tags dt
WHERE dt.tag_id in (1, 12)
GROUP BY dt.document_id
HAVING count(distinct dt.tag_id) = 2;

答案 2 :(得分:1)

实现此目的的另一种方法(调整为按标签标签搜索,我认为这是你的目标,如果不是仅用dt.ID =等替换dt.Label ='etc':

    SELECT documents.id 
    FROM documents d
    WHERE 
    exists (select dt.id from documents_tags dt 
where dt.document_id = d.document_id and dt.label = 'TAG A')
    AND
    exists (select dt.id from documents_tags dt 
where dt.document_id = d.document_id and dt.label = 'TAG B')

答案 3 :(得分:0)

一个WHERE字就足够了:

SELECT documents.id 
FROM documents 
LEFT JOIN documents_tags 
ON documents.id=documents_tags.document_id 
WHERE (documents_tags.tag_id = 1 OR documents_tags.tag_id = 12) ORDER BY documents.label

或者,如果您打算使用n个不同的代码并且不想添加OR documents_tags.tag_id = x,则可以使用IN运算符

SELECT documents.id 
FROM documents 
LEFT JOIN documents_tags 
ON documents.id=documents_tags.document_id 
WHERE documents_tags.tag_id IN(1,12) ORDER BY documents.label

答案 4 :(得分:0)

听起来你在搜索多个文档标签时会尝试聚合结果,所以你应该使用GROUP BY,用于将多行分组到一行:

SELECT documents.id 
FROM documents
LEFT JOIN documents_tags ON documents.id = documents_tags.document_id
WHERE documents_tags.tag_id IN (1, 12)
GROUP BY documents.id

这将为每个与给定标记ID匹配的文档提供一行。并且您可以通过添加到列表而无需太多痛苦来推广到任何标记ID列表。您甚至可以在select语句中添加COUNT(*),以找出给定文档匹配的标记ID数量。