2008-09-01 16 views
5

Tengo tres tablas tag, page, pagetagvarios campos Concatenate en uno con SQL

con los datos siguientes

página

ID  NAME 
1  page 1 
2  page 2 
3  page 3 
4  page 4 

etiqueta

ID  NAME 
1  tag 1 
2  tag 2 
3  tag 3 
4  tag 4 

pagetag

ID PAGEID TAGID 
1 2  1 
2 2  3 
3 3  4 
4 1  1 
5 1  2 
6 1  3 

me gustaría obtener una cadena que contiene los nombres de las etiquetas correspondientes para cada página con SQL en una sola consulta. Esta es mi salida deseada.

ID  NAME  TAGS 
1  page 1  tag 1, tag 2, tag 3 
2  page 2  tag 1, tag 3 
3  page 3  tag 4 
4  page 4  

¿Es esto posible con SQL?


Estoy usando MySQL. No obstante, me gustaría una solución independiente de proveedor de base de datos si es posible.

Respuesta

3

Sergio del Amo:

Sin embargo, no estoy recibiendo las páginas sin las etiquetas. Supongo que necesito escribir mi consulta con las combinaciones externas izquierdas.

SELECT pagetag.id, page.name, group_concat(tag.name) 
FROM 
(
    page LEFT JOIN pagetag ON page.id = pagetag.pageid 
) 
LEFT JOIN tag ON pagetag.tagid = tag.id 
GROUP BY page.id; 
No

una consulta muy bonito, pero debe darle lo que quiere - pagetag.id y group_concat(tag.name) será null de la página 4, en el ejemplo que has publicado anteriormente, pero la página deberá aparecer en el resultados.

3

Sí, usted puede hacerlo a través de la 3 algo como el siguiente:

SELECT page_tag.id, page.name, group_concat(tags.name) 
FROM tag, page, page_tag 
WHERE page_tag.page_id = page.page_id AND page_tag.tag_id = tag.id; 

no ha sido probado, y se podría probablemente ser escrito un poco más eficiente, pero debe empezar!

Además, se asume MySQL, ¡así que puede que no juegue tan bien con MSSQL! Y MySQL no se preocupa por los guiones en los nombres de los campos, por lo que cambió a guiones bajos en los ejemplos anteriores.

0

Creo que es posible que necesite usar varias actualizaciones.

Algo similar (no probado):

select ID as 'PageId', Name as 'PageName', null as 'Tags' 
into #temp 
from [PageTable] 

declare @lastOp int 
set @lastOp = 1 

while @lastOp > 0 
begin 
    update p 
    set p.tags = isnull(tags + ', ', '') + t.[Tagid] 
    from #temp p 
     inner join [TagTable] t 
      on p.[PageId] = t.[PageId] 
    where p.tags not like '%' + t.[Tagid] + '%' 

    set @lastOp == @@rowcount 
end 

select * from #temp 

feo sin embargo.

Ese ejemplo es T-SQL, pero creo que MySql tiene equivalentes a todo lo que se usa.

+1

@Nhan no edite las respuestas solo para cambiar el formato para coincidir con sus opiniones. – Keith

1

Por lo que sé, SQL92 no define cómo se debe hacer la concatenación de cadenas. Esto significa que la mayoría de los motores tienen su propio método.

Si desea un método independiente de la base de datos, tendrá que hacerlo fuera de la base de datos.

(no probado en todo menos en Oracle)

Oracle

SELECT field1 | ', ' | field2 
FROM table; 

MS SQL

SELECT field1 + ', ' + field2 
FROM table; 

MySQL

SELECT concat(field1,', ',field2) 
FROM table; 

PostgeSQL

SELECT field1 || ', ' || field2 
FROM table; 
+0

El estándar SQL define || como el operador de concatenación de cadenas. –

1

Tengo una solución jugando con combinaciones. La consulta es:

SELECT 
    page.id AS id, 
    page.name AS name, 
    tagstable.tags AS tags 
FROM page 
LEFT OUTER JOIN 
(
    SELECT pagetag.pageid, GROUP_CONCAT(distinct tag.name) AS tags 
    FROM tag INNER JOIN pagetag ON tagid = tag.id 
    GROUP BY pagetag.pageid 
) 
AS tagstable ON tagstable.pageid = page.id 
GROUP BY page.id 

Y esta será la salida:

id name tags 
--------------------------- 
1 page 1 tag2,tag3,tag1 
2 page 2 tag1,tag3 
3 page 3 tag4 
4 page 4 NULL 

¿Es posible aumentar la velocidad de las consultas por escrito de otra manera?

0

pagetag.id y group_concat (tag.name) serán nulos para la página 4 en el ejemplo que ha publicado anteriormente, pero la página aparecerá en los resultados.

Usted puede utilizar la función de COALESCE para eliminar los valores nulos si es necesario:

select COALESCE(pagetag.id, '') AS id ... 

Se devolverá el primer valor no nulo desde su lista de parámetros.

Cuestiones relacionadas