Reputation: 19591
I have a of TSQL something like this
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
it's on SQL Server 2012 and it does paging of the records.
Suppose I have 50 records in TAB1 and at a time only 10 is going to be displayed because of paging. Now question I have is does the subquery that I have in there executes for 50 records (which table actually has) or for 10 records (which query returns)?
UPDATE (2014-12-29)
From answers its pretty clear that subquery is executing for 50 records here which is not what I or anyone else would want to have. So if I break down this query into 2 like below would it be better? would subquery execute for paged records only then?
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
Upvotes: 1
Views: 397
Reputation: 433
This query is not a "LEFT OUTER JOIN", it is more "OUTER APPLY" .
In this query, If the relation between the tables is not ONE to ONE, you will get an error message:
"`Msg 512, Level 16, State 1, Line 5 Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. "
there for you need to add to you subquery the SELECT TOP(1) ... ORDER BY ASC/DESC.
FOR EXAMPLE :
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. The execution paln is "NESTED LOOP" (left outer join) . for each row from TAB1 it will access to table TAB2 . so if you are having 100 rows in TAB1 and 50 rows in TAB2 , than you will access to TAB2 100 times .(is it gone a be scan or seek on the tables ? It depends on the index tunning on the table)
Upvotes: 1
Reputation: 4657
For one thing, this is a left outer join query, so it should be written that way (though the query optimizer is likely taking care of that for you, behind the scenes).
To answer your question, this query has to scan the table first, and then return just the rows you wanted. Therefore, if you have 50 records in TAB1 that pass the join condition to TAB2, it's going to go over 50 records before it returns the 10 you asked for.
Re-write your query as this, to be clearer:
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
Upvotes: 1