Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 找到更好的方法来完成每组前1名_Sql_Sql Server_Sql Server 2005 - Fatal编程技术网

Sql 找到更好的方法来完成每组前1名

Sql 找到更好的方法来完成每组前1名,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我正在尝试查找每个id的最新值,该值早于2013年1月1日 下面给出了解决方案,但我知道我这样做是错误的 select id, value from ( select id, value, row_number() over (partition by id order by entry_date desc) as ind from #foo where entry_date < '1/1/2013' ) a where ind = 1 --Results: --

我正在尝试查找每个id的最新值,该值早于2013年1月1日

下面给出了解决方案,但我知道我这样做是错误的

select id, value
from
(
    select id, value, row_number() over (partition by id order by entry_date desc) as ind
    from #foo
    where entry_date < '1/1/2013'
) a where ind = 1

--Results:
--id          value
------------- ---------------------
--1           2.00
--3           5.00
Id 2未返回,因为没有任何早于2013年1月1日的记录

完成我试图做的事情的正确方法是什么?

使用SQL Server 2005,您可以使用排名函数和通用表表达式SCTE

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的最新记录,因此按条目_datedesc而不是值排序

如果要在有多个最新值的情况下使用所有最大值,请将行数替换为密集列。

使用带运算符的选项


您还可以使用子查询来获取结果:

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;

请参见

这是一条相同的路线,但您也可以将带领带的TOP 1与行号结合使用,以消除对子查询的需要:

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函数的不同用途总是好的。

为什么这样做是错误的?我认为嵌套查询对于真实数据集来说效率非常低,因为我选择了整个表,然后,我对第1行的结果为1的结果进行了另一次选择。您在第一行中输入了1/1/2003,无法编辑,因为它少于6个字符。@bendataclear谢谢,修复了。CTE的性能是否与我的解决方案不同,或者是以不同的方式执行相同的操作?@ScottChamberlain:做完全相同的事情。检查执行计划。我使用了不同的顺序,如回答中所述。但也许我误解了这个问题。这是一个输入错误,原来的问题被更新以解决它。但是,如果输入日期不是每个id唯一的,则没有帮助。@Clockwork Muse是的,如果每个日期有多个条目,则这将返回两个条目。您只需添加一个select top 1 order by date desc,以在子查询中获得正确的条件,它就会工作……@IanP您认为为什么需要这样做?写入的查询将返回每个id的一个或多个最新值。因为原始op只指定了一条记录…除非它是在同一天编辑的最新的而不是最新的,以及任何其他记录,否则我键入了一个错误,在over内的顺序应为entry_date。“这在主要问题中已经更正了。@ScottChamberlain谢谢,我没看到。我已经更新了我的答案。什么是领带?我以前从未见过这个关键词被使用过。此外,当我尝试您的方法和我的方法时,我在实际数据集中得到的结果值并不相同。通常,TOP N将返回正好N条记录,即使多条记录符合条件。WITH TIES表示您的查询应该获取N条记录,以及根据您的ORDER BY匹配结果集中最后一条记录的任何其他记录。由于此处的订单将基于行号,因此它将基本匹配行号=1的有趣方法,但被迫进行两次代价高昂的排序操作。顺便说一句,+1
CREATE INDEX x ON #foo(id, entry_date) INCLUDE(value)
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;
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)