Requête SQL donnant des résultats distincts correspondant à plusieurs colonnes
Question
Désolé, je ne pourrais pas donner un meilleur titre à mon problème car je suis assez nouveau en SQL. Je recherche une chaîne de requête SQL qui résout le problème ci-dessous.
Supposons le tableau suivant:
DOCUMENT_ID | TAG ---------------------------- 1 | tag1 1 | tag2 1 | tag3 2 | tag2 3 | tag1 3 | tag2 4 | tag1 5 | tag3
Je souhaite maintenant sélectionner tous les identifiants de document distincts contenant une ou plusieurs balises (mais celles-ci doivent fournir toutes les balises spécifiées). Par exemple: Sélectionnez tous les document_id avec tag1 et tag2 renverra 1 et 3 (mais pas 4 par exemple car il n'a pas tag2).
Quel serait le meilleur moyen de le faire?
Cordialement, Kai
La solution
SELECT document_id
FROM table
WHERE tag = 'tag1' OR tag = 'tag2'
GROUP BY document_id
HAVING COUNT(DISTINCT tag) = 2
Modifier:
Mis à jour par manque de contraintes ...
Autres conseils
Cela suppose que DocumentID et Tag sont la clé primaire.
Edit : La clause HAVING a été modifiée pour compter les balises DISTINCT. Ainsi, la clé primaire n'a pas d'importance.
Données de test
-- 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
Requête
-- Return Results
SELECT DocumentID FROM #table
WHERE Tag IN ('tag1','tag2')
GROUP BY DocumentID
HAVING COUNT(DISTINCT Tag) = 2
Résultats
DocumentID
----------
1
3
select DOCUMENT_ID
TAG in ("tag1", "tag2", ... "tagN")
group by DOCUMENT_ID
having count(*) > N and
Ajustez N et la liste de balises si nécessaire.
Select distinct document_id
from {TABLE}
where tag in ('tag1','tag2')
group by id
having count(tag) >=2
La manière dont vous générez la liste des balises dans la clause where dépend de la structure de votre application. Si vous générez dynamiquement la requête dans votre code, vous pouvez simplement la construire sous la forme d'une grosse chaîne générée dynamiquement.
Nous avons toujours utilisé des procédures stockées pour interroger les données. Dans ce cas, nous transmettons la liste des balises sous forme de document XML. - une procédure comme celle-ci pourrait ressembler à l'une d'elles où l'argument d'entrée serait
<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
FIN