好吧这似乎是一个很长的问题,但我刚刚提供了一些示例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
答案 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