锚定成员从 BOM 中返回 A 直接包含的所有项。对于 CTE 的上一个迭代返回的每个被包含的项,递归成员都通过将 BOM 与 BOMCTE 联接来返回它包含的项。
WITH BOMCTE AS ( SELECT * FROM BOM WHERE itemid = 'A' UNION ALL SELECT BOM.* FROM BOM JOIN BOMCTE ON BOM.itemid = BOMCTE.containsid ) SELECT DISTINCT containsid FROM BOMCTE
以下为结果集:
containsid ---------- B C D E F G J
为了帮助您了解部分爆炸的过程,将它的中间结果直观地表示为树,其中所有项都被展开到它们的被包含的项。图 3 显示了通过使部分 A 和 H 爆炸而形成的树以及项数量。
将原始请求向前推进一步,您可能对获得每个项的累积数量而不是获得项本身更感兴趣。例如,A 包含 2 个单位的 C。C 包含 3 个单位的 E。E 包含 1 个单位的 J。A 所需的 J 的单位总数是沿从 A 通向 J 的路径的数量的乘积:2*3*1 = 6。图 4 显示了在聚合项之前构成 A 的每个项的累积数量。
以下 CTE 计算数量的累积乘积:
WITH BOMCTE(itemid, containsid, qty, cumulativeqty) AS ( SELECT *, qty FROM BOM WHERE itemid = 'A' UNION ALL SELECT BOM.*, BOM.qty * BOMCTE.cumulativeqty FROM BOM JOIN BOMCTE ON BOM.itemid = BOMCTE.containsid ) SELECT * FROM BOMCTE
以下为结果集:
itemid containsid qty cumulativeqty ------ ---------- ----------- ------------- A B 2 2 A C 2 2 A D 2 2 C B 2 4 C E 3 6 E J 1 6 B F 1 4 B G 3 12 B F 1 2 B G 3 6
该 CTE 将 cumulativeqty 列添加到上一个 CTE 中。锚定成员将被包含的项的数量作为 cumulativeqty 返回。对于下一个级别的每个被包含的项,递归成员都将它的数量乘以它的包含项的累积数量。请注意,从多个路径到达的项在结果中出现多次,每一次都带有对应于每个路径的累积数量。这样的输出本身不是很有意义,但是它可以帮助您了解通向每个项只出现一次的最终结果的中间步骤。要获得 A 中的每个项的总数量,请让外部查询按照 containsid 对结果进行分组:
WITH BOMCTE(itemid, containsid, qty, cumulativeqty) AS ( SELECT *, qty FROM BOM WHERE itemid = 'A' UNION ALL SELECT BOM.*, BOM.qty * BOMCTE.cumulativeqty FROM BOM JOIN BOMCTE ON BOM.itemid = BOMCTE.containsid ) SELECT containsid AS itemid, SUM(cumulativeqty) AS totalqty FROM BOMCTE GROUP BY containsid
以下为结果集:
itemid totalqty ------ ----------- B 6 C 2 D 2 E 6 F 6 G 18 J 6
PIVOT 和 UNPIVOT
PIVOT 和 UNPIVOT 是可以在查询的 FROM 子句中指定的新的关系运算符。它们对一个输入表值表达式执行某种操作,并且产生一个输出表作为结果。PIVOT 运算符将行旋转为列,并且可能同时执行聚合。它基于给定的枢轴列扩大输入表表达式,并生成一个带有与枢轴列中的每个唯一值相对应的列的输出表。UNPIVOT 运算符执行与 PIVOT 运算符相反的操作;它将列旋转为行。它基于枢轴列收缩输入表表达式。
PIVOT
PIVOT 运算符可用来处理开放架构方案以及生成交叉分析报表。
在开放架构方案中,您需要用事先不知道或因实体类型而异的属性集来维护实体。应用程序的用户动态定义这些属性。您将属性拆分到不同的行中,并且只为每个实体实例存储相关的属性,而不是在表中预定义很多列并存储很多空值。
PIVOT 使您可以为开放架构和其他需要将行旋转为列的方案生成交叉分析报表,并且可能同时计算聚合并且以有用的形式呈现数据。
开放架构方案的一个示例是跟踪可供拍卖的项目的数据库。某些属性与所有拍卖项目有关,例如,项目类型、项目的制造日期以及它的初始价格。只有与所有项目有关的属性被存储在 AuctionItems 表中:
CREATE TABLE AuctionItems ( itemid INT NOT NULL PRIMARY KEY NONCLUSTERED, itemtype NVARCHAR(30) NOT NULL, whenmade INT NOT NULL, initialprice MONEY NOT NULL, /* other columns */ ) CREATE UNIQUE CLUSTERED INDEX idx_uc_itemtype_itemid ON AuctionItems(itemtype, itemid) INSERT INTO AuctionItems VALUES(1, N'Wine', 1822, 3000) INSERT INTO AuctionItems VALUES(2, N'Wine', 1807, 500) INSERT INTO AuctionItems VALUES(3, N'Chair', 1753, 800000) INSERT INTO AuctionItems VALUES(4, N'Ring', -501, 1000000) INSERT INTO AuctionItems VALUES(5, N'Painting', 1873, 8000000) INSERT INTO AuctionItems VALUES(6, N'Painting', 1889, 8000000)
其他属性特定于项目类型,并且不同类型的新项目被不断地添加。这样的属性可以存储在不同的 ItemAttributes 表中,其中每个项属性都存储在不同的行中。每个行都包含项目 ID、属性名称和属性值:
CREATE TABLE ItemAttributes ( itemid INT NOT NULL REFERENCES AuctionItems, attribute NVARCHAR(30) NOT NULL, value SQL_VARIANT NOT NULL, PRIMARY KEY (itemid, attribute) ) INSERT INTO ItemAttributes VALUES(1, N'manufacturer', CAST(N'ABC' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(1, N'type', CAST(N'Pinot Noir' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(1, N'color', CAST(N'Red' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(2, N'manufacturer', CAST(N'XYZ' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(2, N'type', CAST(N'Porto' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(2, N'color', CAST(N'Red' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(3, N'material', CAST(N'Wood' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(3, N'padding', CAST(N'Silk' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(4, N'material', CAST(N'Gold' AS NVARCHAR(15))) INSERT INTO ItemAttributes VALUES(4, N'inscription', CAST(N'One ring ...' AS NVARCHAR(50))) INSERT INTO ItemAttributes VALUES(4, N'size', CAST(10 AS INT)) INSERT INTO ItemAttributes VALUES(5, N'artist', CAST(N'Claude Monet' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(5, N'name', CAST(N'Field of Poppies' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(5, N'type', CAST(N'Oil' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(5, N'height', CAST(19.625 AS NUMERIC(9,3))) INSERT INTO ItemAttributes VALUES(5, N'width', CAST(25.625 AS NUMERIC(9,3))) INSERT INTO ItemAttributes VALUES(6, N'artist', CAST(N'Vincent Van Gogh' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(6, N'name', CAST(N'The Starry Night' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(6, N'type', CAST(N'Oil' AS NVARCHAR(30))) INSERT INTO ItemAttributes VALUES(6, N'height', CAST(28.75 AS NUMERIC(9,3))) INSERT INTO ItemAttributes VALUES(6, N'width', CAST(36.25 AS NUMERIC(9,3)))
请注意,sql_variant 数据类型被用于 value 列,因为不同的属性值可能具有不同的数据类型。例如,size 属性存储整数属性值,而 name 属性存储字符串属性值。
查看 http://www.qqread.com/sqlserver/f062384005.html相关专题
- SQL Server 数据处理专题 (1856篇文章)
- SQL Server 索引和查询专题 (3320篇文章)
- SQL Server (1813篇文章)
- SQL Server (1815篇文章)
- SQL Server连接中常见错误解决方法 (99次浏览)
- SQL Server的文件恢复技术 (6次浏览)
- 用SQL Server 2005实现WebService (0次浏览)
- 用NetBeans5.0连接SQL Server2005数据库 (0次浏览)
- 使用NetBeans5.0连接SQL Server 2005数据库 (0次浏览)
- 如何使用SQL Server 2000中的XML功能一 (0次浏览)
- 访谈:SQL Server Everywhere仅仅是另一种数据 (0次浏览)
- 地中海船运公司通过SQL Server2005处理5TB的数 (0次浏览)
- 从SQL Server 4.2到SQL Server 2005 (0次浏览)





