下午好。 请帮忙理解。 在AdventureWorks2008R2基础上有表Purchasing.PurchaseOrderDetail,Purchasing.PurchaseOrderHeader,Production.Product。
在其视图中创建一个测试数据库,该数据库显示来自这些表的信息,如下所示:
对于每个单位,OrderQty应该是一个单独的行。如果OrderQty = 5,则视图将为5行
像这样:OrderQty = 4,ReceivedQty = 3.结果在视图中:
ItemNumber ReceivedInd
1 1
2 1
3 1
4 0
我尝试使用游标,但数据库不起作用。怎么写?
declare @in table(i int)
declare @out table (j int)
declare @i int
insert into @in values(7)
insert into @in values(10)
insert into @in values(5)
declare Cur cursor local fast_forward for
select i from @in
open Cur
fetch next from Cur into @i
while ( @@FETCH_STATUS = 0 )
begin
with t as
(
select 1 as val
union all
select val+1 from t where val<@i
)
insert into @out
select val from t
fetch next from Cur into @i
end
close cur
select * from @out
答案 0 :(得分:2)
光标不是必需的(不建议),如果你想重复记录 n 次数,只需加入数字表,如果你没有你可以使用以下方法轻松创建一系列数字:
SELECT ROW_NUMBER() OVER(ORDER BY object_id) FROM sys.all_objects;
因此,您可以使用简单示例:
declare @in table(i int)
insert into @in values(7)
insert into @in values(10)
insert into @in values(5)
SELECT *
FROM @in AS i
CROSS APPLY
( SELECT ROW_NUMBER() OVER(ORDER BY object_id)
FROM sys.all_objects
) AS n (Number)
WHERE i.i >= n.Number
ORDER BY i.i, n.Number;
使示例稍微复杂一些:
DECLARE @T TABLE (ID INT IDENTITY(1, 1), OrderQty INT, ReceivedQty INT);
INSERT @T (OrderQty, ReceivedQty) VALUES (4, 3), (5, 2), (2, 2);
SELECT t.ID,
ItemNumber = n.Number,
ReceivedInd = CASE WHEN n.Number > t.ReceivedQty THEN 0 ELSE 1 END
FROM @T AS t
CROSS APPLY
( SELECT ROW_NUMBER() OVER(ORDER BY object_id)
FROM sys.all_objects
) AS n (Number)
WHERE t.OrderQty >= n.Number
ORDER BY t.ID, n.Number;
相同的查询与JOIN一起使用,执行计划完全相同:
DECLARE @T TABLE (ID INT IDENTITY(1, 1), OrderQty INT, ReceivedQty INT);
INSERT @T (OrderQty, ReceivedQty) VALUES (4, 3), (5, 2), (2, 2);
SELECT t.ID,
ItemNumber = n.Number,
ReceivedInd = CASE WHEN n.Number > t.ReceivedQty THEN 0 ELSE 1 END
FROM @T AS t
INNER JOIN
( SELECT Number = ROW_NUMBER() OVER(ORDER BY object_id)
FROM sys.all_objects
) AS n
ON t.OrderQty >= n.Number
ORDER BY t.ID, n.Number;
答案 1 :(得分:1)
我认为你只是试图将GarethD脚本的结果与来自其他表的数据结合起来,这并不像你想象的那么难。基于下面的AdventureWorks2008的示例:
WITH
E1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS ( SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 )
SELECT
poh.PurchaseOrderID,
pod.PurchaseOrderDetailID,
p.ProductID,
p.Name,
p.ProductNumber,
poh.OrderDate,
poh.ShipDate,
n.N AS ItemNumber,
CASE WHEN n.N > pod.ReceivedQty THEN 0 ELSE 1 END AS ReceivedInd
FROM
Purchasing.PurchaseOrderDetail pod
INNER JOIN
Purchasing.PurchaseOrderHeader poh ON
pod.PurchaseOrderID = poh.PurchaseOrderID
INNER JOIN
Production.Product p ON
pod.ProductID = p.ProductID
INNER JOIN
cteTally n ON
pod.OrderQty >= n.N
ORDER BY pod.PurchaseOrderDetailID, n.N;