SQL Server 2012中的VLOOKUP样式查找

时间:2013-07-04 15:18:07

标签: sql-server tsql

我有一个数据表,可以存储不同日期不同商品的价格。

CREATE TABLE COMMODITIES(
    [MARKET_DATE] [datetime2](0) NOT NULL,
    [THE_TYPE] [numeric](2, 0) NOT NULL,
    [CLOSE_VALUE] [numeric](10, 4) NULL,
) ON [PRIMARY]

GO

MARKET_DATE持有交易日期(日期按升序排列,但非顺序)

CLOSE_VALUE持有价格

THE_TYPE拥有商品类型。

每种商品的交易日期都不同。


我需要获取THE_TYPE = 1的所有日期的清单,以及价格,以及THE_TYPE = 2

的商品的相应价格

如果每种商品的交易日期相同,我可以进行简单的加入(相当于Excel VLOOKUP (, false)

SELECT mr1.market_date
    ,mr1.close_value,mr2.close_value

FROM commodities mr1
LEFT JOIN commodities  mr2 ON mr1.market_date = mr2.market_date
    AND mr2.the_type = 2
WHERE mr1.the_type = 1

但是因为交易日期不一样,我需要查找与Excel VLOOKUP (, true)等效的非完全匹配 - 即mr2中{或1之前}的最大日期{1}}


我正在寻找一个简洁的解决方案。我可以作为一种解决方法,将干预日期输入数据库,这将有效。或者我可以做以下

mr1.market_date

但我希望有一个更简洁(更快)的解决方案


例如,如果表格包含以下内容

SELECT mr1.market_date
    ,mr1.close_value
    , 

            (SELECT top 1 close_value
            FROM commodities mr2

            where mr2.market_date <= mr1.market_date
                AND mr2.the_type = 2
                order by market_date desc
            ) AS close_value

FROM commodities mr1
WHERE mr1.the_type = 1

我会得到

MARKET_DATE CLOSE_VALUE  THE_TYPE
    2012-01-01  300  1
    2012-01-03  310  1
    2012-01-05  310  1
    2012-01-01  400  2
    2012-01-02  420  2
    2012-01-05  430  2

2 个答案:

答案 0 :(得分:2)

您可以使用CROSS APPLY。它可能稍微快一点,但对于这种情况可能不明显:

SELECT mr1.market_date
    ,mr1.close_value as close_value_1
    ,p.close_value as close_value_2
FROM commodities mr1
cross apply
  (SELECT top 1 close_value
        FROM commodities mr2
        where mr2.market_date <= mr1.market_date
            AND mr2.the_type = 2
            order by market_date desc) p
  WHERE mr1.the_type = 1

action

中查看

答案 1 :(得分:1)

WITH OrderedOrders AS
(
    SELECT mr1.market_date
          ,mr1.close_value as mr1close
          ,mr2.close_value as mr2close
          ,ROW_NUMBER() OVER (PARTITION BY mr1.market_date ORDER BY mr2.market_date desc) AS RowNumber
    FROM commodities mr1
    JOIN commodities mr2
      ON mr2.market_date <= mr1.market_date
     AND mr2.the_type = 2
     AND mr1.the_type = 1 
)  
SELECT market_date, mr1close, mr2close  
FROM OrderedOrders 
WHERE RowNumber = 1