2014-12-06 53 views
2

我需要一個查詢來查找購買時物品的價格;價格隨時間變化。 我有兩個表的外鍵鏈接:選擇正確的價格給定購買日期和生效日期

table Albums: 
ID Name PurchaseDate 
1 Album1 2014-05-14 
2 Album2 2014-05-14 
3 Album3 2014-05-14 

table Prices: 
ID AlbumID Price EffDate 
1 1  5.00 2014-01-01 
2 2  5.00 2014-01-01 
3 3  5.00 2014-01-01 
4 3  60.00 2014-04-25 
5 3  700.00 2014-12-12 

當我加入這個查詢表:

select a.ID, a.Name, a.PurchaseDate, p.Price, p.EffDate 
from Albums a 
inner join Prices p 
on a.ID=p.AlbumID; 

我得到以下結果:

ID Name PurchaseDate Price EffDate 
1 Album1 2014-05-14 5.00 2014-01-01 
2 Album2 2014-05-14 5.00 2014-01-01 
3 Album3 2014-05-14 5.00 2014-01-01 
3 Album3 2014-05-14 60.00 2014-04-25 
3 Album3 2014-05-14 700.00 2014-12-12 

問題是Album3的多個結果。可以很容易地獲得與EffDate在未來擺脫記錄:

select a.ID, a.Name, a.PurchaseDate, p.Price, p.EffDate 
from Albums a 
inner join Prices p 
on a.ID=p.AlbumID 
where p.EffDate <= a.PurchaseDate; 

其中給出以下結果:

ID Name PurchaseDate Price EffDate 
1 Album1 2014-05-14 5.00 2014-01-01 
2 Album2 2014-05-14 5.00 2014-01-01 
3 Album3 2014-05-14 5.00 2014-01-01 
3 Album3 2014-05-14 60.00 2014-04-25 

但我需要選擇每一張專輯只有一條記錄,即一個最新的EffDate給予了2014-05-14的購買日期(即2014-04-25的Album3爲60.00)。 我心想,「應該很容易!」但我無法弄清楚它!我試過DISTINCT,與MAX(EffDate),公共表表達式,ROW_NUMBER()與分區BY和ORDER BY子句,FIRST_VALUE(價格)OVER(...)和所有這些的組合,我仍然難倒! (!大概也只是普通的老啞)這裏是我的兩個許多失敗的嘗試:

嘗試:

WITH cte AS 
(
    select a.ID, a.Name, a.PurchaseDate, p.Price, p.EffDate 
    from Albums a 
    inner join Prices p 
    on a.ID=p.AlbumID 
    where p.EffDate <= a.PurchaseDate 
) 
select ID, Name, PurchaseDate, Price, MaxED = (select max(EffDate) from cte) 
from cte; 

---這個查詢和其他類似的變種會給出確切的同結果如之前的上市!!!!聚合函數max(EffDate)顯然對CTE結果沒有影響?!

嘗試B:

select a.ID, a.Name, a.PurchaseDate, p.Price, p.EffDate, pseq 
from Albums a 
inner join 
    (select p.*, row_number() over (partition by AlbumID order by EffDate) as pseq 
    from Prices p) p 
on a.ID=p.AlbumID 
where p.EffDate <= a.PurchaseDate; 

---此查詢還給出了完全相同的結果如上(除了額外的列 'PSEQ')!

其他類似帖子的解決方案,如here沒有與我的情況。

對不起,對於這篇較長的文章,但我認爲清楚地設置示例和我的要求以及我的一些失敗很重要。請幫忙!

P.S.:我正在使用MS SQLEXPRESS 2014和SSMS。是的,我的實際表格和查詢比這個例子複雜得多,但是這個例子儘可能簡潔地提出了我的基本問題。

回答

0

也許這樣的事情會給你的實際價格:

select 
a.ID, 
a.Name, 
a.PurchaseDate, 
(select top 1 p.Price from Prices p where p.AlbumId = a.Id and p.EffDate <= a.PurchaseDate order by p.EffDate desc) as 'Price' 
from Albums a 

輸出:

ID   Name     PurchaseDate   Price 
----------- -------------------- ----------------------- --------------------------------------- 
1   Album1    2014-05-14 00:00:00.000 5.00 
2   Album2    2014-05-14 00:00:00.000 5.00 
3   Album3    2014-05-14 00:00:00.000 60.00 

或者如果你需要一個實際的加入對價格得到其他列,你可以這樣做:

select 
* 
from Albums a 
left join Prices p on 
(
    a.ID = p.AlbumID and 
    p.ID = (select top 1 pp.Id from Prices pp where pp.AlbumId = a.Id and pp.EffDate <= a.PurchaseDate order by pp.EffDate desc) 
) 

並得到這個輸出:

ID   Name     PurchaseDate   ID   AlbumID  Price         EffDate 
----------- -------------------- ----------------------- ----------- ----------- --------------------------------------- ----------------------- 
1   Album1    2014-05-14 00:00:00.000 1   1   5.00         2014-01-01 00:00:00.000 
2   Album2    2014-05-14 00:00:00.000 2   2   5.00         2014-01-01 00:00:00.000 
3   Album3    2014-05-14 00:00:00.000 4   3   60.00         2014-04-25 00:00:00.000 
+0

的建議Romero-謝謝,但它不工作。查詢的結果是:1 \t Album1 \t 2014年5月14日\t 60.00; \t Album2 2014年5月14日\t 60.00; \t Album3 2014年5月14日\t 60.00; – MDGeek 2014-12-06 23:09:31

+0

剛剛添加了另一種方法,實際加入。不是最優雅的查詢,但他們確實工作:) – 2014-12-06 23:36:41

+0

它的工作原理!謝謝你太多了!我在這個愚蠢的問題上浪費了大部分時間! – MDGeek 2014-12-06 23:38:03