Consulta SQL que da resultados distintos que coinciden con múltiples columnas.
Pregunta
Lo siento, no podría proporcionar un mejor título para mi problema ya que soy bastante nuevo en SQL. Estoy buscando una cadena de consulta SQL que resuelva el problema siguiente.
Supongamos la siguiente tabla:
DOCUMENT_ID | TAG ---------------------------- 1 | tag1 1 | tag2 1 | tag3 2 | tag2 3 | tag1 3 | tag2 4 | tag1 5 | tag3
Ahora quiero seleccionar todos los identificadores de documentos distintos que contengan una o más etiquetas (pero deben proporcionar todas las etiquetas especificadas). Por ejemplo: Seleccionar todos los document_id con tag1 y tag2 devolvería 1 y 3 (pero no 4, por ejemplo, ya que no tiene tag2).
¿Cuál sería la mejor manera de hacerlo?
Saludos, Kai
Solución
SELECT document_id
FROM table
WHERE tag = 'tag1' OR tag = 'tag2'
GROUP BY document_id
HAVING COUNT(DISTINCT tag) = 2
Editar:
Actualizado por falta de restricciones ...
Otros consejos
Esto supone que DocumentID y Tag son la clave principal.
Editar : se modificó la cláusula HAVING para contar las etiquetas DISTINCT. De esa manera no importa cuál sea la clave principal.
Datos de prueba
-- 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
Resultados
DocumentID
----------
1
3
select DOCUMENT_ID
TAG in ("tag1", "tag2", ... "tagN")
group by DOCUMENT_ID
having count(*) > N and
Ajusta N y la lista de etiquetas según sea necesario.
Select distinct document_id
from {TABLE}
where tag in ('tag1','tag2')
group by id
having count(tag) >=2
La forma en que se genera la lista de etiquetas en la cláusula where depende de la estructura de la aplicación. Si está generando dinámicamente la consulta como parte de su código, simplemente podría construir la consulta como una gran cadena generada dinámicamente.
Siempre usamos procedimientos almacenados para consultar los datos. En ese caso, pasamos a la lista de etiquetas como un documento XML. - un procedimiento como ese podría parecerse a uno de estos donde el argumento de entrada sería
<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
O
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