开发者

Difference in the latest and second-latest price

I have two tables as follows:

Commodity
---------
Id        Name
1         Test 
2         SecondTest

CommodityPrice
--------------
Id      CommodityID    Price     EffectiveDate
0            1         0.66      05/01/2011
1            1         1.00      06/01/2011
2            1         1.50      07/01/2011
3            2         3.00      05/01/2011         
4            2         5.00      06/01/2011
5            2         10.00     07/01/2011

I'm attempting to write a query with the following output:

Result
-------
Name          PriceChange
Test          0.50
SecondTest    5.00

I've got this query which gets the most recent price, but it's not dealing with price differences yet.

SELECT c1.Name, cp1.Price
FROM Commodities c1
INNER JOIN CommodityPrices cp1
ON c1.Id = cp1.CommodityId
WHERE EffectiveDate = 
(SELECT MAX(cp2.EffectiveDate)
FROM Commo开发者_如何学CdityPrices cp2
WHERE c1.Id = cp2.CommodityId);

I would like to find the price difference between the two most recent prices for a commodity. Note, that this should ignore prices earlier than the most recent two.


This assumes SQL 2005 or later. Just use ROW NUMBER to assign numbers to the rows and then JOIN ON a.id = b.id AND b.rn = a.rn - 1.

WITH
     cte 
     AS (SELECT c.id, 
                c.name, 
                cp.price, 
                cp.effectivedate, 
                Row_number() OVER (PARTITION BY c.id ORDER BY cp.effectivedate 
                DESC) 
                rn 
         FROM   commodity c 
                INNER JOIN commodityprice cp 
                  ON c.id = cp.commodityid) 
SELECT a.name, 
       b.price - a.price pricechange 
FROM   cte a 
       INNER JOIN cte b 
         ON a.id = b.id 
            AND b.rn = a.rn - 1 
WHERE b.rn = 1

Here's the sample data that I used

WITH Commodity as 
(           SELECT 1  as ID , 'Test' as name
 UNION ALL  SELECT 2, 'SecondTest'),
CommodityPrice as 
(   SELECT 1      as Id      , 1         as CommodityID , 1.00  as Price,    '06/01/2011' as EffectiveDate
    UNION ALL SELECT  2            ,1,         1.50      ,'07/01/2011'
    UNION ALL SELECT  4            ,2         ,5.00      ,'06/01/2011'
    UNION ALL SELECT  5            ,2         ,10.00     ,'07/01/2011'
UNION ALL SELECT  0            ,1         ,0.66      ,'05/01/2011'
UNION ALL SELECT  3            ,2         ,3.00      ,'05/01/2011'
 ),

Which produced this output

name       pricechange
---------- ---------------------------------------
Test       0.50
SecondTest 5.00

(2 row(s) affected)

Note: you could also drop AND b.rn = a.rn - 1 from the JOIN and add AND a.rn = 2 to the WHERE


Without ranking functions:

Test data:

declare @CommodityPrice table(id int identity, CommodityID int, Price money, EffectiveDate date)

insert @CommodityPrice(CommodityID, Price, EffectiveDate) 
    values (1, 0.66, '05/01/2011'), (1, 1, '06/01/2011'), (1, 1.5, '07/01/2011'),
        (2, 3, '05/01/2011'), (2, 5, '06/01/2011'), (2, 10, '07/01/2011')

Query:

select a.CommodityID, c2.Price - c1.Price
from
(
    select c1.CommodityID, MAX(c1.EffectiveDate) [m1], MAX(c2.EffectiveDate) [m2]
    from @CommodityPrice c1
    join @CommodityPrice c2 on c2.CommodityID = c1.CommodityID
        and c2.EffectiveDate > c1.EffectiveDate
        and not exists (
            select 1
            from @CommodityPrice c3
            where c3.EffectiveDate > c1.EffectiveDate and c3.EffectiveDate < c2.EffectiveDate
        )
    group by c1.CommodityID
)a
join @CommodityPrice c1 on c1.CommodityID = a.CommodityID and c1.EffectiveDate = a.m1
join @CommodityPrice c2 on c2.CommodityID = a.CommodityID and c2.EffectiveDate = a.m2
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜