如何通过分页计数?

时间:2012-09-25 21:27:56

标签: sql-server

我必须将一些SQL从PostgreSQL迁移到SQL Server(2005+)。在PostgreSQL上我有:

select count(id) as count, date
from table 
group by date 
order by count 
limit 10 offset 25

现在我需要相同的SQL但是对于SQL Server。我是这样做的,但得到错误:Invalid column name 'count'.如何解决?

select * from (
   select row_number() over (order by count) as row, count(id) as count, date 
   from table 
   group by date
) a where a.row >= 25 and a.row < 35

3 个答案:

答案 0 :(得分:5)

除了结尾 ORDER BY之外,你不能在同一范围内按名称引用别名(它是同一范围内窗口函数内的无效引用)

要获得完全相同的结果,可能需要将其扩展为(为了清晰起见,嵌套范围):

SELECT c, d FROM 
(
  SELECT c, d, ROW_NUMBER() OVER (ORDER BY c) AS row FROM 
  (
    SELECT d = [date], c = COUNT(id) FROM dbo.table GROUP BY [date]
  ) AS x
) AS y WHERE row >= 25 AND row < 35;

根据mohan的回答,这可以缩短一点。

SELECT c, d FROM 
(
  SELECT COUNT(id), [date], ROW_NUMBER() OVER (ORDER BY COUNT(id))
   FROM dbo.table GROUP BY [date]
) AS y(c, d, row)
WHERE row >= 25 AND row < 35;

在SQL Server 2012中,OFFSET / FETCH更容易 - 更接近您习惯的语法,但实际上使用的是ANSI兼容语法而不是专有的巫术语。

SELECT c = COUNT(id), d = [date]
FROM dbo.table GROUP BY [date]
ORDER BY COUNT(id)
OFFSET 25 ROWS FETCH NEXT 10 ROWS ONLY;

blogged about this functionality in 2010(那里也有很多好的评论)并且应该投入一些时间做一些严肃的性能测试。

我同意@ajon - 我希望你的真实表格,专栏和查询不会滥用这样的保留字。

答案 1 :(得分:3)

它有效

DECLARE @startrow int=0,@endrow int=0

;with CTE AS (

select row_number() over ( order by count(id)) as row,count(id) AS count, date
from table
group by date 
)
SELECT * FROM CTE 
WHERE  row between @startrow and @endrow

答案 2 :(得分:-3)

我认为这样做会

select * from (
   select row_number() over (order by id) as row, count(id) as count, date 
   from table 
   group by date
) a where a.row >= 25 and a.row < 35

另外,我不知道您使用的是哪个版本的SQL Server,但SQL Server 2012有一个新的Paging功能