TSQL如何将分组表中的联接表中的列连接在一起

时间:2018-09-22 10:39:31

标签: sql-server tsql join string-concatenation

我有2个连接的表:Producto和Productos_ProductosRelacionados

    Producto                Productos_ProductosRelacionados
|id|referencia|         |id|idProducto|idProductoRelacionado|
|1 |    A     |         |1 |    1     |  2                  |
|2 |    B     |         |2 |    1     |  3                  |
|3 |    C     |         |3 |    3     |  4                  |
|4 |    D     |         |4 |    3     |  5                  |
|5 |    E     |

我需要这个:

|idProducto|referencia|
|   1      |  B,C     | 
|   2      |          | 
|   3      |  D,E     |

我有较旧的SQL Server,因此无法使用STRING_AGG 。 到目前为止,我只实现了串联 idProductoRelacionado

|idProducto|idProductoRelacionado|
|   1      |  2,3                |

具有:

SELECT pr1.idProducto
 ,STUFF((
          SELECT ',' + CONVERT(varchar, pr.idProductoRelacionado) 
          FROM [Productos_ProductosRelacionados] as pr
          WHERE pr.idProducto = pr1.idProducto        
          FOR XML PATH('')), 1, 1, '') as RelacionadosID
 FROM [dbo].[Producto] as p1 
 join [Productos_ProductosRelacionados] as pr1 on p1.id = pr1.idProductoRelacionado
 GROUP BY pr1.idProducto

如果我尝试使用相同的方法来连接 referencia 列,则会为我提供:“选择列表中的'dbo.Producto.id'列无效,因为该列未包含在聚合函数或GROUP BY子句。”

select pr1.idProducto
,STUFF((
          SELECT ',' + p.referencia
          FROM [dbo].[Producto] as p
          WHERE p.id = p1.id  
          FOR XML PATH('')), 1, 1, '') as RelacionadosREF
 from [dbo].[Producto] as p1 
 join [Productos_ProductosRelacionados] as pr1 on p1.id = pr1.idProductoRelacionado
 GROUP BY pr1.idProducto

我不明白2个查询之间的区别,为什么第一个查询有效而第二个查询无效。

3 个答案:

答案 0 :(得分:2)

简单联接应该起作用。选中SQLFiddle

SELECT 
  id,
  (SELECT
     cast (p1.referencia as varchar(100)) + ','
   FROM producto p
   LEFT JOIN Productos_ProductosRelacionados pr
         on pr.idProduct = p.id
   LEFT JOIN producto p1
         on p1.id = pr.idProductoRelacionado
   WHERE p.id = src.id
   FOR XML PATH('')) as referencia
FROM
   producto src;

答案 1 :(得分:1)

我前一段时间碰到了这个。您必须在您的填充语句中添加一个联接:

create table    #prod   (
                        id  int,
                        ref varchar(1)
                    )

insert into     #prod values
(1,'A'),
(2,'B'),
(3,'C'),
(4,'D'),
(5,'E')

create table    #prod_rel   (
                                id      int,
                                pid     int,
                                id_rel  int
                            )

insert into     #prod_rel values
(1,1,2),
(2,1,3),
(3,3,4),
(4,3,5)



select  distinct
        pid
        ,STUFF(
                 (SELECT ',' + c.ref FROM #prod_rel b inner join #prod c on c.id = b.id_rel where b.pid = a.pid FOR XML PATH ('')), 1, 1, ''
               )
from    #prod_rel a

drop table  #prod
            ,#prod_rel

答案 2 :(得分:1)

您可以使用递归查询方法,如下所示:

--Create tables for example
select * into #Producto from (
 select 1 id,'A' referential union all select 2,'B' union all select 3,'C' union all select 4,'D' union all select 5,'E'
 ) tmp;

select * into #Productos_ProductosRelacionados from (
select 1 id,1 idProducto,2 idProductoRelacionado union all select 2,1,3 union all select 3,3,4 union all select 4,3,5
) tmp;


-- Recurse query    
With tmp as (
select ROW_NUMBER() over(partition by f1.ID order by f1.id, f3.referential desc) RangID,
count(*)  over(partition by f1.ID order by f1.id) NbID, 
f1.id, f3.referential 
from #Producto f1
left outer join #Productos_ProductosRelacionados f2 on f1.id=f2.idProducto
left outer join #Producto f3 on f2.idProductoRelacionado=f3.id
),
Recurse as (
select f1.id, f1.RangID, f1.NbID, cast(f1.referential as varchar(2000)) referential, 1 rangrecur  from tmp f1 where RangID=1
union all
select f1.id, f1.RangID, f1.NbID, cast(isnull(f1.referential, '') + ',' + isnull(f2.referential, '') as varchar(2000)) referential, f2.rangrecur + 1 as rangrecur  
from tmp f1 inner join Recurse f2 on f1.id=f2.id and f1.RangID-1=f2.RangID
)
select ID, Referential from recurse
where NbID=rangrecur
order by ID;
相关问题