这是我的问题:
我有一个像这样的数据库:
|ID_Brand| Description
------------------------------
|1 | CoolBrandName
|2 | AlsoCoolBrandName
|... | ...
链接到此表我创建了一个像这样的文件表
|ID_file | ID_BRAND | DESCRIPTION | FILECONTENT | ID_CATEGORY
-------------------------------------------------------------
|1 | 1 | File1 |0x0FF0A0B2..| 1
|2 | 1 | File2 |0x2F1A000C..| 2
|3 | 2 | File3 |0X5FB43002..| 1
|4 | 1 | File4 |0x93EEFD13..| 1
|... |... | ... |... | ...
最终使用ID_CATEGORY关联链接到上表的Category表。
|ID_CATEGORY | DESCRIPTION
--------------------------
|1 | Category1
|2 | Category2
|3 | Category3
|4 | Category4
|... | ...
我需要在这些表上显示数据,如数据透视表,按类别分组。 例如,对于上面的数据,我需要输出如下内容:
|BrandName | Category1 | Category2 | Category3 | Category4
------------------------------------------------------------------
|CoolBrandName | File1 | File2 | *NULL* | *NULL*
|AlsoCoolBrandName | File3 | *NULL* | *NULL* | *NULL*
|CoolBrandName | File4 | *NULL* | *NULL* | *NULL*
类别表具有固定的行数。
我尝试从上面的示例开始 http://msdn.microsoft.com/en-us/library/ms177410.aspx 但没有运气。
我需要通过SQL(我使用sql server 2008 r2)或通过Linq实现这一目标。
任何人都可以帮我解决这个问题吗?
我感谢任何建议。
提前致谢 诉
答案 0 :(得分:4)
PIVOT查询类似于GROUP BY查询,但前者隐含分组。数据按所有列进行分组,但只有一列,而这一列成为聚合列。我在my other answer中详细说明了这一点。
在您的情况下,结果集应该按两个明显的列进行分组。它是品牌名称和类别名称。但这还不够,因为根据您的示例,某些文件可能属于同一品牌/类别组,您仍然希望在输出中显示每个单独的文件。所以,显然,必须有另一个标准来分组。
对我而言,第三个标准最明显的选择是某种排名位置。您可以从下面的结果查询中看到,我选择根据字母顺序对文件进行排名。
所以,这是一个适合我的解决方案。首先,我的测试环境 - DDL和样本数据:
DECLARE @Brand TABLE (
ID_Brand int IDENTITY,
Description varchar(50)
);
DECLARE @Category TABLE (
ID_Category int IDENTITY,
Description varchar(50)
);
DECLARE @File TABLE (
ID_File int IDENTITY,
ID_Brand int,
FileContent varbinary(max) DEFAULT (CAST(NEWID() AS varbinary)),
Description varchar(50),
ID_Category int
);
INSERT INTO @Brand (Description) VALUES
('CoolBrandName'),
('AlsoCoolBrandName');
INSERT INTO @Category (Description) VALUES
('Category1'),
('Category2'),
('Category3'),
('Category4');
INSERT INTO @File (ID_Brand, ID_Category, Description) VALUES
(1, 1, 'File1'),
(1, 2, 'File2'),
(2, 1, 'File3'),
(1, 1, 'File4');
这是获取所需输出的查询:
WITH ranked AS (
SELECT
*,
rnk = ROW_NUMBER() OVER (PARTITION BY ID_Brand, ID_Category ORDER BY Description)
FROM @File
),
joined AS (
SELECT
BrandName = b.Description,
CategoryName = c.Description,
FileName = f.Description,
FileRank = f.rnk
FROM ranked f
INNER JOIN @Brand b ON f.ID_Brand = b.ID_Brand
INNER JOIN @Category c ON f.ID_Category = c.ID_Category
)
SELECT
BrandName,
Category1,
Category2,
Category3,
Category4
FROM joined
PIVOT (
MAX(FileName) FOR CategoryName IN (Category1, Category2, Category3, Category4)
) p
ORDER BY Category1
输出本身如下:
BrandName Category1 Category2 Category3 Category4
----------------- --------- --------- --------- ---------
CoolBrandName File1 File2 NULL NULL
AlsoCoolBrandName File3 NULL NULL NULL
CoolBrandName File4 NULL NULL NULL
您可以看到输出中没有第三个标准,即排名。它仍然参与分组,因为它存在于我们正在应用PIVOT子句的行集中,joined
。
最后一点。必须在PIVOT查询中聚合透视列的值。但是,在您的情况下,逻辑上不应该聚合数据,因为应该显示每个文件。在这种情况下,通常使用MAX()
或其他一些聚合函数,保证不会扭曲函数所应用的列的值。您只需要确保每个可能的组包含不超过一个值(我们通过引入排名列来完成)。