Consulta SQL que da resultados distintos que coinciden con múltiples columnas.

StackOverflow https://stackoverflow.com/questions/1202668

  •  05-07-2019
  •  | 
  •  

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

¿Fue útil?

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top