1

我在 SQL Server 2005 中有一些表:

  • ProductID, Name
  • CategoryID, Name
  • TagsID, tagName
  • ProductCategoryproductId, tagId
  • CategoryTagscategoryId, tagId

基本上我需要一个查询,它将在一行上显示与每个产品关联的标签的类别和列表。

例如,有 3 个类别:Animals, Countries, Color.

每一个都有一堆标签。

假设产品 1 有一堆相关的标签,例如:bird, duck, dog, canada, russia, japan, black, red, white

我需要查询结果采用以下格式:

productId, [Category:tag,tag,tag;Category:tag,tag,tag:Category:tag,tag,tag]

1, [Animal:bird,duck,dog;Country:canada,russia,japan;Color:black,red,white]

方括号中的文本应位于 SQL 返回的一列中。

我在这里发现了类似的东西:Concatenate many rows into a single text string?

但我需要更进一步,将它们全部放在一行上,而不是在不同的行上返回不同的类别。

有点难以解释,但希望你能明白。

这可能吗?

提前致谢。

更新:感谢大家的帮助和投入。真的很感激!到目前为止,这是我所拥有的,很接近,但还没有。也许它会帮助你为我弄清楚:D

http://sqlfiddle.com/#!3/eed14/5

4

3 回答 3

1

SQL小提琴

MS SQL Server 2008 架构设置

create table Product
(
  ID int, 
  Name varchar(10)
)

create table Category
(
  ID int, 
  Name varchar(10)
)

create table Tags
(
  ID int, 
  Name varchar(10)
)

create table ProductCategory
(
  productId int,
  categoryId int
)

create table CategoryTags
(
  categoryId int, 
  tagId int
)

insert into Product values(1, 'Product 1')

insert into Category values(1, 'Animals')
insert into Category values(2, 'Countries')
insert into Category values(3, 'Color')

insert into Tags values(1, 'Bird') 
insert into Tags values(2, 'Duck') 
insert into Tags values(3, 'Dog') 
insert into Tags values(4, 'Candada') 
insert into Tags values(5, 'Russia') 
insert into Tags values(6, 'Japan') 
insert into Tags values(7, 'Black') 
insert into Tags values(8, 'Red') 
insert into Tags values(9, 'White') 

insert into ProductCategory values(1, 1)
insert into ProductCategory values(1, 2)
insert into ProductCategory values(1, 3)

insert into CategoryTags values(1, 1)
insert into CategoryTags values(1, 2)
insert into CategoryTags values(1, 3)
insert into CategoryTags values(2, 4)
insert into CategoryTags values(2, 5)
insert into CategoryTags values(2, 6)
insert into CategoryTags values(3, 7)
insert into CategoryTags values(3, 8)
insert into CategoryTags values(3, 9)

查询 1

select P.ID,
       P.Name,
       (
       select ';'+C.Name+':'+
              (
              select ','+T.Name
              from CategoryTags as CT
                inner join Tags as T
                  on CT.tagId = T.ID
              where CT.categoryId = C.ID
              for xml path(''), type
              ).value('substring(text()[1], 2)', 'varchar(max)') 
       from ProductCategory as PC
         inner join Category as C
           on PC.categoryId = C.ID
       where PC.productId = P.ID
       for xml path(''), type
       ).value('substring(text()[1], 2)', 'varchar(max)') as ColumnName
from Product as P

结果

| ID |      NAME |                                                                 COLUMNNAME |
-----------------------------------------------------------------------------------------------
|  1 | Product 1 | Animals:Bird,Duck,Dog;Countries:Candada,Russia,Japan;Color:Black,Red,White |
于 2013-01-07T22:12:39.870 回答
0

只是给一个示例,请试试这个:嗯,这是在 MYSQL 中完成的,它具有最简单的group_concat功能......不过。因为您没有提到您正在使用哪个 RDBMS。

select x.productid, group_concat(c.name), 
group_concat(x.tags)
from (
select p.productid, ct.categoryid,
group_concat(t.tagname) as tags
from productcategory p
left join tags t
on t.id = p.tagid
left join  
categorytags ct
on t.id = ct.tagid
group by p.productid, ct.categoryid) x
left join category c
on c.id = x.categoryid
group by x.productid
;

结果:

PRODUCTID   GROUP_CONCAT(C.NAME)    GROUP_CONCAT(X.TAGS)
1       cat1,cat2                   tag2,tag1,tag1
2       cat1                        tag2

SQLFIDDLE 演示

于 2013-01-07T20:30:51.320 回答
0

这是将这些数据放入单个字符串的一种非常丑陋的方式。但是你可以使用这样的东西:

select distinct 
  p.name ProductName,
  STUFF((SELECT distinct ', ' + 
           c.name +':'+ STUFF((SELECT DISTINCT ', ' + Name 
                               FROM tags t
                               LEFT JOIN CategoryTags ct
                                  on t.id = ct.tagid
                               WHERE c.id = ct.categoryid
                               FOR XML PATH('')), 1, 1, '')
         FROM category c 
         LEFT JOIN CategoryTags ct
           ON ct.categoryid = c.id
         LEFT JOIN productcategory pc
           ON pc.tagid = ct.tagid
         WHERE p.id = pc.productid
         FOR XML PATH('')), 1, 1, '')  List
from product p

请参阅带有演示的 SQL Fiddle

结果是:

| PRODUCTNAME |                                                                               LIST |
----------------------------------------------------------------------------------------------------
|        Test |  Animal: Bird, dog, duck, Color: black, red, white, Country: canada, japan, russia |

编辑#1:这将产生您想要的结果:

select distinct 
  p.name ProductName,
  STUFF((SELECT distinct '; ' + 
           c.name +':'+ STUFF((SELECT DISTINCT ', ' + Name 
                               FROM catalogTags t
                               LEFT JOIN catalogProductTags pt
                                 on t.id = pt.catalogTagId
                               LEFT JOIN catalogCategoryTags ct
                                 on pt.catalogTagId = ct.catalogTagId
                               WHERE c.id = ct.catalogCategoryId
                                  AND p.id = pt.catalogProductId
                               FOR XML PATH('')), 1, 1, '')
         FROM catalogProductTags pt
         LEFT JOIN catalogCategoryTags ct
           ON pt.catalogTagId = ct.catalogTagId
         LEFT JOIN catalogCategory c 
           ON ct.catalogCategoryId = c.id
         WHERE p.id = pt.catalogProductId
         FOR XML PATH('')), 1, 1, '')  List
from catalogProduct p;

请参阅SQL Fiddle with Demo。这可能可以重构为更清洁的版本。

结果是:

| PRODUCTNAME |                                                        LIST |
-----------------------------------------------------------------------------
|     tshirt1 |                           Animals: dog; Color: black, white |
|     tshirt2 |              Animals: dog; Color: blue, red; Countries: USA |
|     tshirt3 |  Color: blue, pink, red, white; Countries: Australia, Japan |
于 2013-01-07T22:08:51.333 回答