Following @mdb's answer to apply pagination using SQL SERVER, I find it hard to retrieve distinct records when the main table is joined to other tables for a one-to-many relationship, i.e, A person has many addresses.
Use case, suppose I want to retrieve all persons which has an address in New York given tables #temp_person
and #temp_addresses
, I would join them on PersonID
and OwnerID
.
The problem arises when there are multiple addresses for a person, the result set contains duplicate records.
To make it clearer, here's a sample query with data:
Sample Data:
create table #temp_person (
PersonID int not null,
FullName varchar(max) not null
)
create table #temp_addresses(
AddressID int identity not null,
OwnerID int not null,
Address1 varchar(max),
City varchar(max)
)
insert into #temp_person
values
(1, 'Sample One'),
(2, 'Sample Two'),
(3, 'Sample Three')
insert into #temp_addresses (OwnerID, Address1, City)
values
(1, 'Somewhere East Of', 'New York'),
(1, 'Somewhere West Of', 'New York'),
(2, 'blah blah blah', 'Atlantis'),
(2, 'Address2 Of Sample Two', 'New York'),
(2, 'Address3 Of Sample Two', 'Nowhere City'),
(3, 'Address1 Of Sample Three', 'New York'),
(3, 'Address2 Of Sample Three', 'Seattle')
--drop table #temp_addresses, #temp_person
Pagination Query:
SELECT
(
CAST( RowNum as varchar(MAX) )
+ '/'
+ CAST(TotalCount as varchar(MAX))
) as ResultPosition
, PersonID
, FullName
FROM (
SELECT DISTINCT
ROW_NUMBER() OVER(ORDER BY p.FullName ASC) as RowNum
, p.PersonID
, p.FullName
, Count(1) OVER() as TotalCount
FROM #temp_person p
LEFT JOIN #temp_addresses a
ON p.PersonID = a.OwnerID
WHERE City = 'New York'
) as RowConstrainedResult
WHERE RowNum > 0 AND RowNum <= 3
ORDER BY RowNum
Expected Results:
ResultPosition PersonID FullName
1/3 1 Sample One
2/3 2 Sample Two
3/3 3 Sample Three
Actual Results:
ResultPosition PersonID FullName
1/4 1 Sample One
2/4 1 Sample One
3/4 3 Sample Three
As you can see, the inner query is returning multiple records due to the join with #temp_addresses
.
Is there a way we could only return unique records by PersonID
?
UPDATE:
Actual use case is for an "Advanced Search" functionality where the user can search using different filters, i.e, name, firstname, last name, birthdate, address, etc.. The <WHERE_CLAUSE>
and <JOIN_STATEMENTS>
in the query are added dynamically so GROUP BY
is not applicable here.
Also, please address the "Pagination" scheme for this question. That is, I want to retrieve only N
number of results from Start
while also retrieving the total count of the results as if they are not paged. i.e, I retrieve only 25 rows out of a total of 500 results.