SQL Server:" distinct"的分页记录

时间:2016-01-09 02:10:08

标签: sql-server

我有三个表格和列,如下所示

resource: id, location.
subject: id, name
resource_subject: resource_id, subject_id

"资源"之间的关系和"主题"是多对多的。这是我的查询:

select r.* from resource r 
inner join resource_subject subject on r.id = subject.resource_id 
where (subject.subject_id= 2 or subject.subject_id= 4) 

如上所述查询可能会产生重复记录,因为一个资源可能属于多个主题。因此,要删除重复项,我使用 distinct ,如下所示:

select distinct r.* from resource r 
inner join resource_subject subject on r.id = subject.resource_id 
where (subject.subject_id= 2 or subject.subject_id= 4) 

现在我想对独特记录进行分页。我读了这篇SO帖子,

What is the best way to paginate results in SQL Server

我对使用 ROW_NUMBER()感兴趣。但是,使用ROW_NUMBER()会使重复记录唯一:

select distinct ROW_NUMBER() over( order by r.id asc) AS rownum, r.* from resource r 
inner join resource_subject subject on r.id = subject.resource_id 
where (subject.subject_id= 2 or subject.subject_id= 4) 

如何在#34; distinct"之后对记录执行ROW_NUMBER()?

2 个答案:

答案 0 :(得分:2)

使用DENSE_RANK()代替

ROW_NUMBER() is to SELECT what DENSE_RANK() is to SELECT DISTINCTDENSE_RANK()的以下应用程序将生成行号,就好像它们在应用DISTINCT后生成一样。

select distinct DENSE_RANK() over( order by r.id asc) AS rownum, r.* from resource r 
inner join resource_subject subject on r.id = subject.resource_id 
where (subject.subject_id= 2 or subject.subject_id= 4) 

它是如何运作的?

最好通过示例解释,也可以从linked article

解释
SELECT
  v, 
  ROW_NUMBER() OVER(ORDER BY v),
  RANK()       OVER(ORDER BY v),
  DENSE_RANK() OVER(ORDER BY v)
FROM (
  VALUES('a'),('a'),('a'),('b'),
        ('c'),('c'),('d'),('e')
) t(v);

以上产量:

| V | ROW_NUMBER | RANK | DENSE_RANK |
|---|------------|------|------------|
| a |          1 |    1 |          1 |
| a |          2 |    1 |          1 |
| a |          3 |    1 |          1 |
| b |          4 |    4 |          2 |
| c |          5 |    5 |          3 |
| c |          6 |    5 |          3 |
| d |          7 |    7 |          4 |
| e |          8 |    8 |          5 |

答案 1 :(得分:1)

在外部查询中生成row_number

;WITH cte 
     AS (SELECT Row_number()OVER( ORDER BY id ASC) AS rownum, 
                * 
         FROM   (SELECT DISTINCT r.* 
                 FROM   resource r 
                        INNER JOIN resource_subject subject 
                                ON r.id = subject.resource_id 
                 WHERE  subject.subject_id IN ( 2, 4 )) A) 
SELECT * 
FROM   cte 
WHERE  rownum >= 1 
       AND rownum <= 10 

但如果您使用的是Sql Server 2012+,请使用OFFSET进行分页,这将比Row_number

SELECT DISTINCT r.* 
FROM   resource r 
       INNER JOIN resource_subject subject 
               ON r.id = subject.resource_id 
WHERE  subject.subject_id IN ( 2, 4 ) 
ORDER  BY r.id 
offset 1 rows FETCH next 10 rows only;