【问题标题】:tSQL Return first row of partitiontSQL 返回分区的第一行
【发布时间】:2017-05-08 14:55:54
【问题描述】:

目标是使用尽可能少的资源返回分区的第一行。到目前为止,我已经看到了使用建议:

with customerinfo_CTE as
(
select row_number() over(partition by customer order by year desc) as RNumber, *
from customerInfo
)

select * 
from customerinfo_CTE 
where RNumber = 1

所以,我有一个 customerInfo 表,我们可以在其中跟踪过去的客户详细信息(即:联系信息、公司名称等)。此时我正在使用 CTE,但也可以使用#Temp 表或@Variable 表。

我希望有一种方法可以通过在 CTE(或其他)中获取当年唯一的第一条记录,然后在连接或脚本的其他部分中使用它来提高性能。

现在,我正在使用:

with customerinfo_CTE as
(
select row_number() over(partition by customer order by year desc) as RNumber, *
from customerInfo
)

select * 
from customerOrders a
inner join  customerinfo_CTE b
on a.CustomerID = b.CustomerID
where b.RNumber = 1

虽然这给了我想要的结果,但我希望有一种方法可以简化它,以便在 CTE 声明中获得第一个结果,而无需在连接的 where 子句中过滤后端。

提前致谢。

【问题讨论】:

  • 欢迎来到Apply加入的世界
  • 好吧,您在 CTE 中所做的相同,您可以将其插入到临时表或表变量中,然后使用过滤后的 CTE(将 WHERE 条件放在 CTE 查询中)。使用表变量很棘手,因为查询优化器总是会为它估计 1 个返回的行,但您当然可以尝试检查什么对您有用。
  • 优化器可能足够聪明

标签: sql sql-server tsql row-number


【解决方案1】:

交叉应用使用内联视图来获取订单的相关信息记录,但使用交叉应用运算符(不是真正的联接),它为 customerOrders 中的每个记录执行此操作,根据订单返回每个客户的 TOP 1 记录在内联视图中定义。

SELECT * 
FROM CUSTOMERORDERS A
CROSS APPLY (SELECT top 1 * 
             FROM customerInfo B
             WHERE A.CustomerID = B.customerID
             ORDER by year desc) C

虽然基于名称的表格对我来说似乎倒退了;但根据你的例子似乎是正确的。

我可以看到很多订单,但只有 1 条信息记录...所以我想您会想要按订单年份排名最高的订单...但也许不是。

所以也许你是这个意思?

SELECT * 
FROM CustomerInfo A
CROSS APPLY (SELECT top 1 * 
             FROM CUSTOMERORDERS B
             WHERE A.CustomerID = B.customerID
             ORDER by year desc) C

但也许您每年都有每个客户的信息记录......所以也许没有......

还有一篇相关文章解释了应用程序的用法以及一些很好的示例以及为什么可以提高性能:https://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/

【讨论】:

  • 不错的答案,但不保证效率更高。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-23
  • 2017-06-29
  • 2019-02-11
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多