获取特定日期的正确审核详细信息

时间:2014-09-08 14:29:55

标签: sql sql-server-2008 tsql

好吧这似乎是一个很长的问题,但我刚刚提供了一些示例SQL,以便您可以很好地了解我要做的事情。

基本上我有一个当前价格的股票表。当价格发生变化时,触发器会在审计表中使用旧价格创建记录,并将validTo字段设置为前一天。因此,如果我今天将苹果的价格从1:10改为1:20 ......我认为1:10的价格是整个前进的一天,旧的1:20的价格一直持续到昨天的午夜。

好的很酷...所以我想。我现在的问题是,我想把我所有的销售情况拿出去,并在销售日期取出该库存商品的价格。请注意,在我的示例中,有些价格没有像芒果那样改变,因此没有要添加的审计记录,因为当前价格是唯一的价格。

我以为我会在销售表上使用Cross应用但有问题。

以下是示例代码...到目前为止..

    drop table #CurrentStock
    drop table #AuditTable
    drop table #Sales

    create table #CurrentStock
    (
        StockID     int identity ,
        Stock       varchar(50),
        Quantity    int,
        Price       decimal(5,2),
        Supplier    varchar(50)
    )

    go

    create table #AuditTable
    (
        AuditID int identity,
        StockID int,
        Price   decimal(5,2),
        ValidTo date
    )

    go

    create table #sales
    (
        SaleID  int identity,
        StockID int,
        AmountSold  int,
        DateSold    date
    )

    --Insert 4 stock items and the current price
    insert into #CurrentStock values ('Apple', 200, 1.50, 'Jones');
    insert into #CurrentStock values ('Banana', 300, 1.10, 'Smiths');
    insert into #CurrentStock values ('Oranges', 100, 1.75, 'Ables');
    insert into #CurrentStock values ('Pears', 400, 2.50, 'Jones');
    insert into #CurrentStock values ('Mango', 350, 3.50, 'Jacks'); -- Note this has no audit as the price hasnt changed

    --Insert the Price Changes for the stock
    -- Note the ValidTo field... is up to and including that date so for the first item for apple
    -- the price of 1:10 was valid up to and including 2014-05-01. The next price change of 1.18
    -- would then be valid from 2014-05-02 up to and including 2014-05-07

    insert into #auditTable values (1, 1.10, '2014-05-01');
    insert into #auditTable values (1, 1.18, '2014-05-07');
    insert into #auditTable values (1, 1.22, '2014-05-18');
    insert into #auditTable values (2, 1.11, '2014-05-11');
    insert into #auditTable values (2, 1.14, '2014-05-17');
    insert into #auditTable values (2, 1.16, '2014-05-23');
    insert into #auditTable values (2, 1.12, '2014-05-28');
    insert into #auditTable values (3, 1.86, '2014-05-17');
    insert into #auditTable values (3, 1.92, '2014-05-20');
    insert into #auditTable values (4, 2.62, '2014-05-11');
    insert into #auditTable values (4, 2.67, '2014-05-12');
    insert into #auditTable values (4, 2.92, '2014-05-20');

    -- Create Some Sales

    -- Apples
    insert #sales values ( 1,2,'2014-05-01');   -- price should be 1.10
    insert #sales values ( 1,3,'2014-05-03');   -- price should be 1.18
    insert #sales values ( 1,1,'2014-05-08');   -- price should be 1.22
    insert #sales values ( 1,4,'2014-05-11');   -- price should be 1.22
    insert #sales values ( 1,3,'2014-05-14');   -- price should be 1.22
    insert #sales values ( 1,4,'2014-05-20');   -- price should be current price in stock table

    -- Bananna
    insert #sales values ( 2,2,'2014-05-01');   -- price should be 1.11
    insert #sales values ( 2,5,'2014-05-10');   -- price should be 1.11
    insert #sales values ( 2,2,'2014-05-12');   -- price should be 1.14
    insert #sales values ( 2,4,'2014-05-17');   -- price should be 1.14
    insert #sales values ( 2,2,'2014-05-25');   -- price should be 1.12

    -- Now I want to get the stock that has a price change after the 2014-05-15
    -- If there is no price change like in the case of Mango then we want the current Price
    select * from
    (
        SELECT
            StockId,
            Rank() OVER (Partition By StockId Order By ValidTo Desc) as RowNum,     
            Price,
            ValidTo
        FROM
            #auditTable aud
        WHERE
                ValidTo > '2014-05-15'  -- filter out the records that we dont need

        UNION 

        SELECT
            StockId,
            0 as RowNum,  -- make this Row num 0 so we can group on them        
            Price,
            cast(GETDATE() as DATE)
        FROM 
            #CurrentStock cs
    ) stockList order by StockID,RowNum 

因此,所有的好处都取决于已经改变的价格。所以现在的问题是我希望得到所有的销售并加入股票并获得股票在销售期间所处的价格......所以我需要将上述查询包装在CTE或其他东西中我可以交叉申请。

我估计可能会创建一个带有日期和库存ID的函数并返回价格可能是最好的并使用交叉应用...但我目前没有权利创建一个函数并且需要做很长的事情。

任何帮助都非常感谢...关于M

2 个答案:

答案 0 :(得分:0)

我认为这就是你要找的东西。无论如何,这是一个选择..

使用select来获取审计过滤器并保存到临时表(#TempAudit)..

            select * 
        into #TempAudit    -- saved into temp table called #TempAudit
        from
        (
            SELECT
                StockId,
                Rank() OVER (Partition By StockId Order By ValidTo Desc) as RowNum,     
                Price,
                ValidTo
            FROM
                #auditTable aud
            WHERE
                    ValidTo > '2014-05-15'  -- filter out the records that we dont need

            UNION 

            SELECT
                StockId,
                0 as RowNum,  -- make this Row num 0 so we can group on them        
                Price,
                cast(GETDATE() as DATE)
            FROM 
                #CurrentStock cs
        ) stockList 
         order by StockID,RowNum 

使用#TempAudit表..

修改:

        select *
from #Sales sales
    inner join
    (
        select  ta1.StockId, ta1.RowNum, ta1.Price
        , ta1.ValidTo as ValidDateFromInclusive
        , ISNULL(ta2.ValidTo, '9999-12-31') as ValidDateToExclusive
        from #TempAudit ta1
    left outer join
        #TempAudit ta2
    on ta1.stockId = ta2.stockid and ta1.RowNum - 1 = ta2.rownum
    union all
    select StockId, RowNum+1, Price, '1900-01-01' as ValidDateFromInclusive, ValidTo as ValidDateToExclusive
        from #tempAudit ta
        where rownum = (select max(rownum) from #tempAudit where StockId = ta.StockId)
    ) AuditWithDates
    on sales.StockId = AuditWithDates.StockId 
        and (sales.DateSold >= AuditWithDates.ValidDateFromInclusive and sales.DateSold < AuditWithDates.ValidDateToExclusive)
order by sales.SaleID

答案 1 :(得分:0)

这样的事情怎么样?

select *
from #sales s
cross apply
(
    select top 1 cs.StockID
        , cs.Stock
        , ISNULL(a.ValidTo, getdate()) as ValidTo
        , ISNULL(a.Price, cs.Price) as Price
    from #CurrentStock cs
    left join #AuditTable a on a.StockID = cs.StockID
    where s.DateSold <= ISNULL(a.ValidTo, getdate())
        and s.StockID = cs.StockID
    order by ISNULL(a.ValidTo, getdate()) 
) x