使用 SQL Server 中不同表的数据创建逗号分隔值字符串

问题描述

我有以下数据库模型:

criteria table:
criteria_id   criteria_name      is_range
  1         product_category        0
  2         product_subcategory     0
  3             items               1
  4            criteria_4           1


evaluation_grid table:
evaluation_grid_id  criteria_id start_value  end_value  provider    property_1    property_2 property_3      
    1                       1       3           NULL    internal        1             1             1
    2                       1       1           NULL    internal        1             1             1
    3                       2       1           NULL    internal        1             2             1
    4                       3       1           100     internal        2             1             1
    5                       4       1           50      internal        2             2             1
    6                       1       2           NULL    external        2             8             1
    7                       2       2           NULL    external        2             5             1
    8                       3       1           150     external        2             2             2
    9                       3       1           100     external        2             3             1

 product_category table:
   id    name
   1     test1 
   2     test2
   3     test3

 product_subcategory table:
   id    name
   1     producttest1
   2     producttest2
   3     producttest3

我想要实现的是返回这样的值:

 criteria             start_value    end_value  provider   property_1   property_2  property_3
 product_category     test3,test1     NULL     internal        1           1           1
 product_subcategory  producttest1     NULL     internal        1           2           1
 items                     1           100      internal        2           1           1
 criteria_4                1           50       internal        2           2           1
 product_category         test2       NULL      external        2           8           1
 product_subcategory  producttest2    NULL      external        2           5           1
 items                     1           150      external        2           2           2
 criteria_4                1           100      external        2           3           1

基本上保持表evaluation_grid的顺序,但只对不是范围的标准进行分组 在基于 start_value、end_value、provier、property_1、property_2 和 property_3 的逗号分隔值字符串中

我是这样试的:

 SELECT c.criteria_name AS criteria,CASE WHEN c.criteria_id = 1
    THEN 
       (IsNull(STUFF((SELECT ',' + RTRIM(LTRIM(pc.name))
        FROM product_category pc 
        INNER JOIN [evaluation_grid] eg ON eg.start_value=pc.id
        WHERE srsg.criteria_id=c.criteria_id
        FOR XML PATH('')),1,2,''),'')) 
    WHEN c.criteria_id = 2
        THEN (IsNull(STUFF((SELECT ',' + RTRIM(LTRIM(psc.name))
            FROM product_subcategory psc 
            INNER JOIN [evaluation_grid] eg ON eg.start_value=psc.id
            WHERE srsg.criteria_id=c.criteria_id
            FOR XML PATH('')
            ),3,'')) 
    ELSE 
        CAST(eg.start_value AS VARCHAR)
    END AS start_value,eg.end_value AS end_value,eg.provider AS provider,eg.property_1 AS property_1,eg.property_2 AS property_2,eg.property_3 AS property_3
FROM [evaluation_grid] eg
INNER JOIN criteria c ON eg.criteria_id = crs.criteria_id
GROUP BY c.criteria_name,c.criteria_id,c.is_range,eg.start_value,eg.end_value,eg.provider,eg.property_1,eg.property_2,eg.property_3

但是它返回了错误的数据,如下所示:

criteria                    start_value      end_value      provider   property_1   property_2  property_3
product_category     test3,test1,test2        NULL        internal        1           1           1
product_category     test3,test2        NULL        external        2           8           1
product_category     test3,test2        NULL        internal        1           1           1
product_subcategory  producttest1,producttest2  NULL        internal        1           2           1
product_subcategory  producttest1,producttest2  NULL        external        2           5           1
items                        1                  100         internal        1           1           1
items                        1                  150         external        2           2           2
criteria_4                   1                  50          internal        2           2           1
criteria_4                   1                  100         external        2           3           1

我尝试了一些带有“with cte;”的版本同样,但还没有设法找到解决方案,是的,我已经检查了类似的问题。 :) PS:我不能使用 STRING_AGG,因为我们的 sql Server 版本低于 2017。 任何建议将不胜感激,谢谢!

解决方法

据我所知,此查询返回您正在寻找的确切输出。

with cte as (
    select c.criteria_name,eg.evaluation_grid_id,case when c.criteria_id = 1 then pc.[name]                                       
                when c.criteria_id = 2 then psc.[name]
                else null end pc_cat,c.criteria_id,c.is_range,eg.start_value,eg.end_value,eg.[provider],eg.property_1,eg.property_2,eg.property_3
    from @evaluation_grid eg
         join @criteria c ON eg.criteria_id = c.criteria_id
         left join @product_category pc on eg.start_value=pc.id
         left join @product_subcategory psc on eg.start_value=psc.id)
select c.criteria_name as criteria,case when c.is_range=0 then 
                STUFF((SELECT ',' + RTRIM(LTRIM(c2.pc_cat))
                       FROM cte c2 
                       WHERE c2.criteria_id=c.criteria_id
                             and c2.is_range=c.is_range
                             and c2.[provider]=c.[provider]
                             and c2.property_1=c.property_1
                             and c2.property_2=c.property_2
                             and c2.property_3=c.property_3
                       FOR XML PATH('')),1,2,'')
            else max(cast(c.start_value as varchar(50))) end as start_value,c.end_value,c.[provider],c.property_1,c.property_2,c.property_3
from cte c
group by c.criteria_name,c.property_3
order by max(c.evaluation_grid_id);

输出

criteria            start_value     end_value   provider    property_1  property_2  property_3
product_category    test3,test1    NULL        internal    1           1           1
product_subcategory producttest1    NULL        internal    1           2           1
items               1               100         internal    2           1           1
criteria_4          1               50          internal    2           2           1
product_category    test2           NULL        external    2           8           1
product_subcategory producttest2    NULL        external    2           5           1
items               1               150         external    2           2           2
criteria_4          1               100         external    2           3           1
,

按照要求有点困难。您能否查看下面的设置和结果,并让我们知道所需的结果集应该是什么?

declare @criteria table (criteria_id int,criteria_name varchar(50),is_range bit)
insert into @criteria
    values(1,'product_category',0),(2,'product_subcategory',(3,'items',1),(4,'criteria_4',1);

declare @evaluation_grid table (evaluation_grid_id int,criteria_id int,start_value int,end_value int,[provider] varchar(50),property_1 int,property_2 int,property_3  int);
insert into @evaluation_grid
    values
    (1,3,NULL,'internal',100,(5,4,50,(6,'external',8,(7,5,(8,150,2),(9,1)

declare @product_category table (id int,[name] varchar(50))
insert into @product_category
    values (1,'test1'),'test2'),'test3'),'test4');

declare @product_subcategory table (id int,[name] varchar(50))
insert into @product_subcategory
    values (1,'producttest1'),'producttest2'),'producttest3');   


select  c.criteria_name,stuff(( select ',' + ipc.[name] 
                from @evaluation_grid ieg 
                join @product_category ipc on ieg.start_value = ipc.id 
                where [provider] = eg.[provider] and property_1 = eg.property_1 and property_2 = eg.property_2 and property_3 = eg.property_3
                order by ieg.evaluation_grid_id 
                for xml path('')),'') as start_value,end_value,[provider],property_1,property_2,property_3
from    @evaluation_grid eg
join    @criteria c on eg.criteria_id = c.criteria_id
where   c.is_range = 0
group
by      c.criteria_name,property_3
union all
select  c.criteria_name,cast(start_value as varchar(10)),property_3
from    @evaluation_grid eg
join    @criteria c on eg.criteria_id = c.criteria_id
where   c.is_range = 1;