SQL Server 2012分页和子查询

时间:2014-12-24 19:22:43

标签: sql sql-server sql-server-2012

我有类似这样的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

2 个答案:

答案 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)

  1. 此查询不是“LEFT OUTER JOIN”,更多是“外部申请”。

  2. 在此查询中,如果表之间的关系不是一对一,您将收到一条错误消息:

  3. “`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次。(它是不是扫描或搜索表?它取决于表上的索引调整)