观点问题

时间:2014-08-14 11:39:09

标签: sql sql-server-2008 view

下午好。 请帮忙理解。 在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

2 个答案:

答案 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;