簡體   English   中英

使用t-sql根據其他表中的日期查找值

[英]Using t-sql to lookup value based on dates in other table

我面臨以下挑戰。 我有2張桌子。 第一個表包含特定時間(即價格目錄)自行車的價值變化。 這意味着某個產品的某個價格有效,直到該表中有一個新價格。

Product |   RowNr | Year |  Month | Value
------------------------------------------
Bike1   |    1    | 2009 |    8   |  100
Bike1   |    2    | 2010 |    2   |  400
Bike1   |    3    | 2011 |    4   |  300
Bike1   |    4    | 2012 |    9   |  100
Bike1   |    5    | 2013 |    2   |  500
Bike1   |    6    | 2013 |    5   |  200
Bike2   |    1    | 2013 |    1   | 5000
Bike2   |    2    | 2013 |    2   | 4000
Bike2   |    3    | 2014 |    6   | 2000
Bike2   |    4    | 2014 |   10   | 4000

第二個表包含我要確定自行車價值的日期(基於表1中的信息)。

Product | Date       | Value
-------------------------
Bike1   |  3/01/2008 |  ?
Bike1   | 04/30/2011 |  ?
Bike1   |  5/08/2009 |  ?
Bike1   | 10/10/2012 |  ?
Bike1   |  7/01/2014 |  ?

因此,第1行和第3行應獲得值“ 400”,第2行“ 300”,第4行“ 100”和第5行“ 200”等。

有誰知道如何在T-SQL中實現? 我已經對第一個表進行了分區,但是可以在后續步驟中使用一些建議。

非常感謝,

您可以執行類似的操作,該方法將使用小於或等於產品表日期的價格檢索產品的最新價格目錄值。

SELECT p.product
    , p.date
    , valueAsOfDate = 
    (   SELECT TOP 1 c.value
        FROM priceCatalogue c
        WHERE c.product = p.product
            AND convert(date, 
                    convert(varchar(4), c.year) + '-' 
                    + convert(varchar(2), c.month)  
                    + '-1' 
                ) <= p.date
        --this order by will ensure that the most recent price is used
        ORDER BY c.year desc, c.month desc 
    )
FROM product p

該表結構不是理想的……您最好在priceCatalogue表中使用“ AsOfDate”列,這樣您就不必將priceCatalogue表中的值轉換為日期來進行比較。 如果這是新開發的,則將priceCatalogue表更改為具有asOfDate列(它是日期數據類型)。 如果這是從另一個數據源填充的現有表,那么您可以考慮將持久化的計算列添加到表中。 http://msdn.microsoft.com/en-us/library/ms188300.aspx

通過productCatalogue表上的asOfDate列,您可以使用索引來進行SARG支持的查詢( 是什么使SQL語句可存儲? )。

SELECT p.product
    , p.date
    , valueAsOfDate = 
    (   SELECT TOP 1 c.value
        FROM priceCatalogue c
        WHERE c.product = p.product
            AND c.asOfDate <= p.date
        --this order by will ensure that the most recent price is used
        ORDER BY c.year desc, c.month desc 
    )
FROM product p

只需使用YEAR()MONTH()函數獲取日期的那些部分,然后將它們加入版本表中即可。

select
from product p
inner join productVersion pv 
  on p.product = pv.product
  and Year(p.Date) = pv.Year
  and Month(p.Date) = pv.Month

Xivan,我認為您的第1行和第3行的值都應為“ 100”,因為3/1/2008和5/8/2009小於8 / xx / 2009。 由於表結構不理想,因此必須創建一些計算列以進行計算。希望以下查詢對您有用。

WITH cte
AS (
SELECT p.*
    ,(
        SELECT min(p1.rownr) rownr
        FROM product p1
        WHERE p1.rownr > p.rownr
            AND p.product = p1.product
        GROUP BY p1.product
        ) AS nrownr
    ,(
        SELECT max(p1.rownr) rownr
        FROM product p1
        WHERE p1.rownr < p.rownr
            AND p.product = p1.product
        GROUP BY p1.product
        ) AS prownr
FROM product p
)
        SELECT pd.*
        ,c.value
    FROM product_date pd
    LEFT JOIN cte c ON pd.product = c.product
    LEFT JOIN product p ON c.product = p.product
        AND c.nrownr = p.rownr
    LEFT JOIN product p1 ON c.product = p1.product
        AND c.prownr = p1.rownr
    WHERE (pd.DATE !> convert(DATE, convert(VARCHAR(4), (
                        CASE WHEN p.year IS NOT NULL THEN p.year ELSE 9999 END)) + '-'         + convert(VARCHAR(2), (
                        CASE WHEN p.month IS NOT NULL THEN p.month ELSE 12 END)) + '-' + '1')
            AND 
pd.DATE !< convert(DATE, convert(VARCHAR(4), c.year) + '-' + convert(VARCHAR(2), c.month) + '-' + '1'))
        OR 
(pd.DATE !> convert(DATE, convert(VARCHAR(4), (
                        CASE WHEN p1.year IS NOT NULL THEN NULL ELSE 2009 END)) + '-' +
convert(VARCHAR(2), ( CASE WHEN p1.month IS NOT NULL THEN NULL ELSE 8 END)) + '-' +'1')
            )

http://sqlfiddle.com/#!3/22c1d/2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM