SQL查询,提供与多个列匹配的不同结果

时间:2009-07-29 19:57:44

标签: sql database h2

抱歉,我无法为我的问题提供更好的标题,因为我对SQL很新。 我正在寻找一个解决以下问题的SQL查询字符串。

我们假设下表:

DOCUMENT_ID |     TAG
----------------------------
   1        |   tag1
   1        |   tag2
   1        |   tag3
   2        |   tag2
   3        |   tag1
   3        |   tag2
   4        |   tag1
   5        |   tag3

现在我想选择包含一个或多个标签的所有不同文档ID(但必须提供所有指定的标签)。 例如: 选择带有tag1的所有document_id,并且tag2将返回1和3(但不是4,例如因为它没有tag2)。

最好的方法是什么?

此致 启

4 个答案:

答案 0 :(得分:14)

SELECT document_id
FROM table
WHERE tag = 'tag1' OR tag = 'tag2'
GROUP BY document_id
HAVING COUNT(DISTINCT tag) = 2

编辑:

因缺乏约束而更新......

答案 1 :(得分:7)

这假定DocumentID和Tag是主键。

编辑:更改了HAVING子句以计算DISTINCT标记。这样,主键是什么并不重要。

测试数据

-- Populate Test Data
CREATE TABLE #table (
  DocumentID varchar(8) NOT NULL, 
  Tag varchar(8) NOT NULL
)

INSERT INTO #table VALUES ('1','tag1')
INSERT INTO #table VALUES ('1','tag2')
INSERT INTO #table VALUES ('1','tag3')
INSERT INTO #table VALUES ('2','tag2')
INSERT INTO #table VALUES ('3','tag1')
INSERT INTO #table VALUES ('3','tag2')
INSERT INTO #table VALUES ('4','tag1')
INSERT INTO #table VALUES ('5','tag3')

INSERT INTO #table VALUES ('3','tag2')  -- Edit: test duplicate tags

<强>查询

-- Return Results
SELECT DocumentID FROM #table
WHERE Tag IN ('tag1','tag2')
GROUP BY DocumentID
HAVING COUNT(DISTINCT Tag) = 2

<强>结果

DocumentID
----------
1
3

答案 2 :(得分:1)

select DOCUMENT_ID
      TAG in ("tag1", "tag2", ... "tagN")
   group by DOCUMENT_ID
   having count(*) > N and 

根据需要调整N和标签列表。

答案 3 :(得分:-1)

Select distinct document_id 
from {TABLE} 
where tag in ('tag1','tag2')
group by id 
having count(tag) >=2 

如何在where子句中生成标记列表取决于您的应用程序结构。如果您在代码中动态生成查询,那么您可以简单地将查询构造为一个动态生成的大字符串。

我们总是使用存储过程来查询数据。在这种情况下,我们将标记列表作为XML文档传递。 - 像这样的过程可能看起来像输入参数

之一
<tags>
   <tag>tag1</tag>
   <tag>tag2</tag>
</tags>


CREATE PROCEDURE [dbo].[GetDocumentIdsByTag]
@tagList xml
AS
BEGIN

declare @tagCount int
select @tagCount = count(distinct *) from @tagList.nodes('tags/tag') R(tags)


SELECT DISTINCT documentid
FROM {TABLE}
JOIN @tagList.nodes('tags/tag') R(tags) ON {TABLE}.tag = tags.value('.','varchar(20)')
group by id 
having count(distict tag) >= @tagCount 

END

OR

CREATE PROCEDURE [dbo].[GetDocumentIdsByTag]
@tagList xml
AS
BEGIN

declare @tagCount int
select @tagCount = count(*) from @tagList.nodes('tags/tag') R(tags)


SELECT DISTINCT documentid
FROM {TABLE}
WHERE tag in
(
SELECT tags.value('.','varchar(20)') 
FROM @tagList.nodes('tags/tag') R(tags)
}
group by id 
having count( distinct tag) >= @tagCount 
END

END