Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用SQL获取分页的不同记录(不重复)_Sql_Sql Server_Tsql - Fatal编程技术网

使用SQL获取分页的不同记录(不重复)

使用SQL获取分页的不同记录(不重复),sql,sql-server,tsql,Sql,Sql Server,Tsql,按照@mdb的答案,我发现当主表与其他表以一对多的关系连接时,很难检索不同的记录,也就是说,一个人有许多地址 在用例中,假设我想要检索所有在纽约有地址的人,在给定的表\temp\u person和\temp\u addresses中,我会在PersonID和OwnerID上加入他们 当一个人有多个地址时,问题就会出现,结果集包含重复的记录 为了更清楚,下面是一个包含数据的示例查询: 样本数据: create table #temp_person ( PersonID int not nu

按照@mdb的答案,我发现当主表与其他表以一对多的关系连接时,很难检索不同的记录,也就是说,一个人有许多地址

在用例中,假设我想要检索所有在纽约有地址的人,在给定的表
\temp\u person
\temp\u addresses
中,我会在
PersonID
OwnerID上加入他们

当一个人有多个地址时,问题就会出现,结果集包含重复的记录

为了更清楚,下面是一个包含数据的示例查询:

样本数据:

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
 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
ResultPosition  PersonID    FullName
   1/3           1         Sample One
   2/3           2         Sample Two
   3/3           3        Sample Three
ResultPosition  PersonID    FullName
   1/4            1        Sample One
   2/4            1        Sample One
   3/4            3       Sample Three
ResultPosition  PersonID    FullName
1/3             1           Sample One
2/3             2           Sample Two
3/3             3           Sample Three
分页查询:

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
 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
ResultPosition  PersonID    FullName
   1/3           1         Sample One
   2/3           2         Sample Two
   3/3           3        Sample Three
ResultPosition  PersonID    FullName
   1/4            1        Sample One
   2/4            1        Sample One
   3/4            3       Sample Three
ResultPosition  PersonID    FullName
1/3             1           Sample One
2/3             2           Sample Two
3/3             3           Sample Three
实际结果:

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
 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
ResultPosition  PersonID    FullName
   1/3           1         Sample One
   2/3           2         Sample Two
   3/3           3        Sample Three
ResultPosition  PersonID    FullName
   1/4            1        Sample One
   2/4            1        Sample One
   3/4            3       Sample Three
ResultPosition  PersonID    FullName
1/3             1           Sample One
2/3             2           Sample Two
3/3             3           Sample Three
如您所见,由于与
#temp_addresses
的联接,内部查询将返回多个记录

有没有办法只通过
PersonID
返回唯一的记录

更新:

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
 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
ResultPosition  PersonID    FullName
   1/3           1         Sample One
   2/3           2         Sample Two
   3/3           3        Sample Three
ResultPosition  PersonID    FullName
   1/4            1        Sample One
   2/4            1        Sample One
   3/4            3       Sample Three
ResultPosition  PersonID    FullName
1/3             1           Sample One
2/3             2           Sample Two
3/3             3           Sample Three
实际用例是“高级搜索”功能,用户可以使用不同的过滤器进行搜索,即姓名、名、姓、出生日期、地址等。。查询中的
是动态添加的,因此
分组依据
在此不适用


另外,请针对这个问题提出“分页”方案。也就是说,我只想从
Start
中检索
N
结果的数量,同时检索结果的总计数,就好像它们没有分页一样。i、 在总共500个结果中,我只检索了25行。

只需按
PersonID进行分组,无需使用
子查询

SELECT 
         cast(row_number() over (order by (select 1)) as varchar(max)) +'/'+
         cast(Count(1) OVER() as varchar(max)) ResultPosition,  
         p.PersonID,
         max(p.FullName) FullName
FROM #temp_person p
LEFT JOIN #temp_addresses a ON p.PersonID = a.OwnerID
WHERE City = 'New York'
group by p.PersonID
编辑:我将使用
CTE
进行分页

;with cte as
(
    SELECT 
         row_number() over(order by (select 1)) rn,
         cast(row_number() over (order by (select 1)) as varchar(max)) +'/'+
         cast(Count(1) OVER() as varchar(max)) ResultPosition,  
         p.PersonID,
         max(p.FullName) FullName
    FROM #temp_person p
    LEFT JOIN #temp_addresses a ON p.PersonID = a.OwnerID
    WHERE City = 'New York'
    group by p.PersonID
) 
select * from cte 
where rn > 0  and rn <= 2
declare @page int =1, @rowsPage int = 25

select distinct position, ResultPosition = cast(position as varchar(10)) + '/' + cast(count(*) OVER() as varchar(10)), *
from(
    SELECT  position = DENSE_RANK () over (order by p.PersonID),
            p.PersonID,
            p.FullName
    FROM #temp_person p
        LEFT JOIN #temp_addresses a ON 
            p.PersonID = a.OwnerID
    WHERE City = 'New York'
    ) r
where position between @rowsPage*(@page-1)+1 and @rowsPage*@page

在使用
ROW\u NUMBER()
之前,需要有不同的行

如果您将按
城市
进行筛选,则无需使用
左加入
。改用
内部联接

select ResultPosition = cast(row_number() over (order by (r.PersonID)) as varchar(max)) +'/'+ cast(Count(r.PersonID) OVER() as varchar(max)), *
from(
    SELECT distinct p.PersonID,
                    p.FullName
    FROM #temp_person p
        JOIN #temp_addresses a ON 
            p.PersonID = a.OwnerID
    WHERE City = 'New York') r
编辑: 考虑分页

;with cte as
(
    SELECT 
         row_number() over(order by (select 1)) rn,
         cast(row_number() over (order by (select 1)) as varchar(max)) +'/'+
         cast(Count(1) OVER() as varchar(max)) ResultPosition,  
         p.PersonID,
         max(p.FullName) FullName
    FROM #temp_person p
    LEFT JOIN #temp_addresses a ON p.PersonID = a.OwnerID
    WHERE City = 'New York'
    group by p.PersonID
) 
select * from cte 
where rn > 0  and rn <= 2
declare @page int =1, @rowsPage int = 25

select distinct position, ResultPosition = cast(position as varchar(10)) + '/' + cast(count(*) OVER() as varchar(10)), *
from(
    SELECT  position = DENSE_RANK () over (order by p.PersonID),
            p.PersonID,
            p.FullName
    FROM #temp_person p
        LEFT JOIN #temp_addresses a ON 
            p.PersonID = a.OwnerID
    WHERE City = 'New York'
    ) r
where position between @rowsPage*(@page-1)+1 and @rowsPage*@page

Geoman Yabes,检查这是否有帮助。。。给出示例中预期的结果,您可以使用RowNum进行分页:-

SELECT *
FROM
(SELECT ROW_NUMBER() OVER(ORDER BY RowConstrainedResult.PersonId ASC) As RowNum,
        Count(1) OVER() As TotalRows,
        RowConstrainedResult.PersonId,
        RowConstrainedResult.FullName
 FROM (
    SELECT 
          RANK() OVER(PARTITION BY p.PersonId ORDER BY a.Address1 ASC) as Ranking 
        , p.PersonID
        , p.FullName
    FROM #temp_person p
    INNER JOIN #temp_addresses a ON p.PersonID = a.OwnerID WHERE City = 'New York'
) as RowConstrainedResult WHERE Ranking = 1) Filtered
Where RowNum > 0 And RowNum <= 4

我想检索分页结果,而不是整个查询。另外,虽然您的答案适用于上述示例测试用例,但我恐怕无法在实际项目中使用
groupby
。甚至没有解决我提到的分页功能。
DISTINCT
在我的用例中不可靠,因为连接和WHERE语句是动态添加的。请再看看我的问题。我编辑了,再编辑一次。我看了你的编辑。因此,如果不能使用DISTINCT,请将其删除。稠密_RANK()不需要区分。将“不同”移动到外部选择。