我正在尝试查找早于value
的{{1}} id
{/ 1}}
1/1/2013
以下为我提供了解决方案,但我知道我这样做是错误的。
create table #foo
(
id int,
value money,
entry_date datetime
)
insert into #foo values (1, 1.00, '1/1/2012')
insert into #foo values (1, 2.00, '2/1/2012')
insert into #foo values (1, 7.00, '1/1/2013')
insert into #foo values (2, 1.00, '1/1/2013')
insert into #foo values (2, 1.00, '2/1/2013')
insert into #foo values (3, 5.00, '3/1/2012')
由于没有任何超过1/1/2013的记录,因此未返回ID 2.
完成我想要做的事情的正确方法是什么?
答案 0 :(得分:6)
您还可以使用子查询来获得结果:
select f1.id, f1.value
from #foo f1
inner join
(
select id, max(entry_date) entry_date
from #foo
where entry_date < '1/1/2013'
group by id
) f2
on f1.id = f2.id
and f1.entry_date = f2.entry_date;
答案 1 :(得分:3)
为了完整性,其中:
id
ids
的列表(可能通过外键引用表);和 ...使用APPLY
的查询比表(或索引)的单次扫描更有效:
create table foo
(
id int not null primary key
);
create table bar
(
id int not null references foo,
value money not null,
entry_date datetime not null,
primary key (id, entry_date)
);
insert foo (id)
values (1), (2), (3), (4);
insert bar
(id, value, entry_date)
values
(1, 1.00, '1/1/2012'),
(1, 2.00, '2/1/2012'),
(1, 7.00, '1/1/2013'),
(2, 1.00, '1/1/2013'),
(2, 1.00, '2/1/2013'),
(3, 5.00, '3/1/2012');
select
foo.id,
c.value
from foo
cross apply
(
select top (1) -- with ties, if desired
bar.value
from bar
where
bar.id = foo.id
and bar.entry_date < '20130101'
order by
bar.entry_date desc
) as c
order by
foo.id;
参见 SQLfiddle
答案 2 :(得分:2)
这是相同的,但您也可以将TOP 1 WITH TIES
与ROW_NUMBER()
结合使用,以消除对子查询的需求:
select top 1 with ties id, value
from #foo
where entry_date < '1/1/2013'
order by row_number() over (partition by id order by entry_date desc)
在我看来,这有点清洁。不幸的是,它也可以执行稍慢。尽管如此,了解SQL函数的不同用途总是很好。
答案 3 :(得分:1)
使用SQL-Server 2005
,您有排名函数和公用表表达式(CTE)。
WITH CTE AS
(
SELECT id,value,entry_date,
RN = ROW_NUMBER() OVER (PARTITION BY id ORDER BY entry_date DESC)
FROM dbo.TableName
WHERE entry_date < '1/1/2013'
)
SELECT id,value,entry_date FROM CTE WHERE RN = 1
会返回每个ID的最新记录,因此ORDER BY entry_date DESC
代替value
。
如果您想要所有“max-recent”值(如果有多个),请将ROW_NUMBER
替换为DENSE_RANK
。
答案 4 :(得分:1)