Pergunta

Desculpe, eu não poderia fornecer um título melhor para o meu problema como eu sou muito novo para SQL. Estou à procura de uma cadeia de consulta SQL que resolve o problema abaixo.

Vamos supor que a tabela a seguir:

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

Agora eu quero selecionar todos de ID do documento distintas que contenham uma ou mais marcas (mas aqueles devem fornecer etiquetas de todos os especificados). Por exemplo: Selecionar tudo document_id está com tag1 e tag2 voltaria 1 e 3 (mas não 4 por exemplo, como ele não tem tag2).

Qual seria a melhor maneira de fazer isso?

Saudações, Kai

Foi útil?

Solução

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

Editar:

Atualizado por falta de restrições ...

Outras dicas

Isso pressupõe DocumentID e Tag são a chave primária.

Editar : Mudou HAVING para contar marcas distintas. Dessa forma, não importa o que a chave primária é.

Dados de Teste

-- 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

Consulta

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

Resultados

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

Ajustar N ea lista tag conforme necessário.

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

Como você gera a lista de marcas na cláusula WHERE depende da sua estrutura de aplicação. Se você estiver gerando dinamicamente a consulta como parte de seu código, então você pode simplesmente construir a consulta como uma grande cadeia gerada dinamicamente.

Nós sempre utilizados procedimentos armazenados para consultar os dados. Nesse caso, passamos na lista de tags como um documento XML. - um procedimento como esse poderia ser algo como um deles, onde o argumento de entrada seria

<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

ou

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top