我有类似这样的TSQL
declare
@_RowsPerPage INT = 10,
@_PageNumber INT = 1
select *,
(
select col
from TAB2
where TAB2.num = TAB1.num
)
from TAB1
order by TAB1.num
OFFSET (@_PageNumber - 1) * @_RowsPerPage ROWS
FETCH NEXT @_RowsPerPage ROWS ONLY
它在SQL Server 2012上,它会对记录进行分页。
假设我在TAB1中有50条记录,并且由于分页,一次只会显示10条记录。 现在的问题是,我在那里执行的子查询是否执行50条记录(哪个表实际上有)或10条记录(哪个查询返回)?
更新(2014-12-29)
从答案可以清楚地看出,子查询正在执行50条记录,这不是我或其他任何人想要的。因此,如果我将此查询分解为2,如下所示会更好吗?那么子查询只会执行分页记录吗?
declare
@_RowsPerPage INT = 10,
@_PageNumber INT = 1
declare @_tempTbl table (num int)
insert into @_tempTbl
select num
from TAB1
order by TAB1.num
OFFSET (@_PageNumber - 1) * @_RowsPerPage ROWS
FETCH NEXT @_RowsPerPage ROWS ONLY
select TAB1.*,
(
select col
from TAB2
where TAB2.num = TAB1.num
)
from @_tempTbl as TAB1
答案 0 :(得分:1)
首先,这是一个左外连接查询,因此它应该以这种方式编写(尽管查询优化器可能会在幕后为您处理)。
要回答您的问题,此查询必须先扫描表格,然后只返回您想要的行。因此,如果TAB1中有50条记录将连接条件传递给TAB2,那么它将返回50条记录,然后返回您要求的10条记录。
重新编写您的查询,更清楚:
declare @_RowsPerPage INT = 10,
@_PageNumber INT = 1
select TAB1.*, TAB2.col
from TAB1 LEFT OUTER JOIN TAB2 ON TAB1.num = TAB2.num
order by TAB1.num
OFFSET (@_PageNumber - 1) * @_RowsPerPage ROWS
FETCH NEXT @_RowsPerPage ROWS ONLY
答案 1 :(得分:1)
此查询不是“LEFT OUTER JOIN”,更多是“外部申请”。
在此查询中,如果表之间的关系不是一对一,您将收到一条错误消息:
“`Msg 512,Level 16,State 1,Line 5 子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。 “
你需要在子查询中添加SELECT TOP(1)... ORDER BY ASC / DESC。
例如:
USE NORTHWND
GO
declare
@_RowsPerPage INT = 10,
@_PageNumber INT = 1
select *,
(
select TOP(1)
TAB2.OrderID
from dbo.[Orders] TAB2
where TAB2.CustomerID = TAB1.CustomerID
ORDER BY OrderID asc
)
from [dbo].[Customers] TAB1
order by TAB1.PostalCode
OFFSET (@_PageNumber - 1) * @_RowsPerPage ROWS
FETCH NEXT @_RowsPerPage ROWS ONLY ;
go
2。执行paln是“NESTED LOOP”(左外连接)。对于来自TAB1的每一行,它将访问表TAB2。 所以,如果你在TAB1中有100行,在TAB2中有50行,那么你将会访问TAB2 100次。(它是不是扫描或搜索表?它取决于表上的索引调整)