Domanda

Siamo spiacenti, non potrei fornire un titolo migliore per il mio problema poiché sono abbastanza nuovo in SQL. Sto cercando una stringa di query SQL che risolva il problema seguente.

Supponiamo che la seguente tabella:

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

Ora voglio selezionare tutti gli ID documento distinti che contengono uno o più tag (ma devono fornire tutti i tag specificati). Per esempio: Seleziona tutti i document_id con tag1 e tag2 restituirà 1 e 3 (ma non 4 ad esempio perché non ha tag2).

Quale sarebbe il modo migliore per farlo?

Saluti, Kai

È stato utile?

Soluzione

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

Modifica:

Aggiornato per mancanza di vincoli ...

Altri suggerimenti

Ciò presuppone che DocumentID e Tag siano la chiave primaria.

Modifica : modificata la clausola HAVING per contare i tag DISTINCT. In questo modo non importa quale sia la chiave primaria.

Dati di prova

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

Query

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

Risultati

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

Regola N e l'elenco dei tag secondo necessità.

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

La modalità di generazione dell'elenco di tag nella clausola where dipende dalla struttura dell'applicazione. Se stai generando dinamicamente la query come parte del tuo codice, potresti semplicemente costruire la query come una grande stringa generata dinamicamente.

Abbiamo sempre usato le procedure memorizzate per interrogare i dati. In tal caso, passiamo nell'elenco dei tag come documento XML. - una procedura del genere potrebbe assomigliare a una di queste in cui l'argomento di input sarebbe

<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

OPPURE

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

FINE

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top