0

我有一个 Items 表,其中包含大约 30000 条记录,我的客户分组到其中的 Groupings 表,我的 Products 排序到的 Categories 表,以及存储哪些 Items 进入哪些类别的 Product_Categories 表(作为每个分组有自己的印刷目录,其中项目根据分组分为不同的类别)。

+----------+   +---------------+   +---------------+   +-------------------+
| Items    |   | Groupings     |   | Categories    |   | Item_Categories   |
+----------+   +---------------+   +---------------+   +-------------------+
| Item_ID  |   | Grouping_ID   |   | Category_ID   |   | Item_ID           |
| Item_Name|   | Grouping_Name |   | Category_Name |   | Grouping_ID       |
+----------+   +---------------+   +---------------+   | Category_ID       |
                                                       +-------------------+

例如,我的产品“Red Paint”在“艺术家”分组(我将其缩写为“AR”)中的客户的“美术用品”类别中,但它出现在我的客户的“油漆 - 丙烯酸”类别中'Painters' (PN) 分组,以及我的客户在'Schools' 分组中的'Back to School' 类别。

因此,关系存储在 Item_Categories 表中,如下所示(为清楚起见,显示名称而不是 ID):

+------------+--------------+-----------------+
| Item_ID    | Grouping_ID  | Category_ID     |
+------------+--------------+-----------------+
| Red Paint  | Artists      | Art Supplies    |
| Red Paint  | Painters     | Paint - Acrylic |
| Red Paint  | Schools      | Back to School  |
+------------+--------------+-----------------+

现在我需要的是一个 SQL Server 2005 查询,它在标题行中提供项目和所有分组,以及网格格式的实际关系,如下所示:

+--------------+-----------------+-----------------+----------------+
| Item_Name    | Artists         | Painters        | Schools        |
+--------------+-----------------+-----------------+----------------+
| Red Paint    | Art Supplies    | Paint - Acrylic | Back to School |
| Blue Paint   | Art Supplies    | Paint - Acrylic | Back to School |
| 1" Brush     | Art Supplies    | Brushes - Small | Back to School |
+--------------+-----------------+-----------------+----------------+

我希望我的要求是有道理的。我的直觉告诉我,如果我使用“交叉表”类型的方法,这可以通过单个查询来实现,但是我需要的输出格式的(明显)复杂性让我头晕目眩。

感谢您花时间阅读我的问题;我希望你能提供一些指导。

4

1 回答 1

1

您将数据上的行转换为列的过程类型称为PIVOT。有几种方法可以在 sql server 中透视数据。

您可以将聚合函数与 CASE 表达式一起使用:

select i.item_name,
  max(case when g.grouping_name = 'Artists' then c.category_name end) Artists,
  max(case when g.grouping_name = 'Painters' then c.category_name end) Painters,
  max(case when g.grouping_name = 'Schools' then c.category_name end) Schools
from items i
left join item_categories ic
  on i.item_id = ic.item_id
left join groupings g
  on ic.grouping_id = g.grouping_id
left join categories c
  on ic.category_id = c.category_id
group by i.item_name;

请参阅带有演示的 SQL Fiddle

如果您知道值,则可以使用 PIVOT 对查询进行硬编码:

select item_name,
 Artists, Painters, Schools 
from
(
  select i.item_name,
    g.grouping_name,
    c.category_name
  from items i
  left join item_categories ic
    on i.item_id = ic.item_id
  left join groupings g
    on ic.grouping_id = g.grouping_id
  left join categories c
    on ic.category_id = c.category_id
) d
pivot
(
  max(category_name)
  for grouping_name in (Artists, Painters, Schools)
) piv;

请参阅SQL Fiddle with Demo

但似乎您可能有未知数量的值要转换为列,如果是这种情况,那么您将需要使用动态 SQL 来获得解决方案:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Grouping_Name) 
                    from Groupings
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT item_name, ' + @cols + ' 
             from 
             (
                select i.item_name,
                  g.grouping_name,
                  c.category_name
                from items i
                left join item_categories ic
                  on i.item_id = ic.item_id
                left join groupings g
                  on ic.grouping_id = g.grouping_id
                left join categories c
                  on ic.category_id = c.category_id
            ) x
            pivot 
            (
                max(category_name)
                for grouping_name in (' + @cols + ')
            ) p '

execute(@query);

请参阅SQL Fiddle with Demo。所有版本都会给出一个结果:

|  ITEM_NAME |      ARTISTS |        PAINTERS |        SCHOOLS |
----------------------------------------------------------------
|   1" Brush | Art Supplies |          (null) | Back to School |
| Blue Paint | Art Supplies | Paint - Acrylic | Back to School |
|  Red Paint | Art Supplies | Paint - Acrylic | Back to School |
于 2013-07-24T15:23:24.340 回答