我需要一个查询来查找购买时商品的价格;价格随时间而变化。 我有两个由外键链接的表:
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
但是我需要为每个专辑选择一个记录,即给出2014-05-14的PurchaseDates时最新EffDate的记录(即2014-04-25的Album3为60.00)。 我心想,#34;这应该很容易!&#34;但我无法弄明白!我尝试过DISTINCT,用MAX(EffDate),公用表表达式,ROW_NUMBER()和PARTITION BY和ORDER BY子句聚合,FIRST_VALUE(Price)OVER(...),以及所有这些的组合,我和# 39; m仍然难倒! (也可能只是简单的老哑!)以下是我的许多失败尝试中的两个:
尝试A:
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;
---此查询也提供与上面完全相同的结果(额外列&#39; pseq&#39;除外)!
here等其他类似帖子中的解决方案与我的情况无关。
对于长篇文章感到抱歉,但我认为清楚地设置示例和我的要求以及我的一些失败很重要。请帮助!
P.S。:我正在使用MS SQLEXPRESS 2014和SSMS。是的,我的实际表和查询比这个例子复杂得多,但是这个例子尽可能简洁地呈现了我的基本问题。
答案 0 :(得分: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