我有这张桌子
CREATE TABLE [dbo].[friend_blocked_list](
[subdomain] [varchar](50) NOT NULL,
[un] [nvarchar](50) NOT NULL,
[friend] [nvarchar](50) NOT NULL,
[is_blocked] [bit] NOT NULL,
[approved] [bit] NOT NULL)
我使用以下查询从中选择数据。选择查询结合了已添加为好友的用户和已被用户添加为好友的用户
declare @un varchar(50), @subdomain varchar(50)
set @un='user2';
set @subdomain ='test.domain.com';
WITH FRIENDS as
(
SELECT friend
FROM friend_blocked_list
WHERE un=@un and subdomain=@subdomain and approved=1 and is_blocked=0
UNION ALL
SELECT un as friend
FROM friend_blocked_list
WHERE friend=@un and subdomain=@subdomain and approved=1 and is_blocked=0
)
select friend from FRIENDS group by FRIENDS.friend order by FRIENDS.friend asc
它适用于少量数据,但我希望能够在服务器端进行分页以减少负载。我正在尝试将它与下面的分页 sp 结合起来
create PROCEDURE [dbo].[Paging]
@subdomain varchar(50),
@un varchar(50),
@PageNumber int,
@PageSize int
AS
BEGIN
--paging
DECLARE @FirstRow INT,@LastRow INT,@RowCount INT,@PageCount INT
--find recordcount and pages
SELECT @RowCount = COUNT(*), @PageCount = COUNT(*) / @PageSize
FROM friend_blocked_list
WHERE subdomain=@subdomain AND un=@un AND approved=1 AND is_blocked=0;
--- calculate pages
IF @RowCount % @PageSize != 0 SET @PageCount = @PageCount + 1
IF @PageNumber < 1 SET @PageNumber = 1
IF @PageNumber > @PageCount SET @PageNumber = @PageCount
SELECT
CurrentPage = @PageNumber,
TotalPages = @PageCount,
TotalRows = @RowCount
-- mora calculation
SELECT @FirstRow = ( @PageNumber - 1) * @PageSize + 1,
@LastRow = (@PageNumber - 1) * @PageSize + @PageSize ;
WITH MyTopics AS
(
SELECT *, ROW_NUMBER() OVER (order by un asc) AS RowNumber
FROM friend_blocked_list
WHERE subdomain=@subdomain AND un=@un AND approved=1 AND is_blocked=0
)
SELECT *
FROM MyTopics
WHERE RowNumber BETWEEN @FirstRow AND @LastRow
ORDER BY RowNumber ASC;
end
但一如既往,我遇到了麻烦:)。主要问题是我查询中的
UNION ALL
。它阻止我使用ROW_NUMBER() OVER
。
有什么想法吗?
以下是更新的寻呼程序:
CREATE PROCEDURE [dbo].[Paging]
@subdomain varchar(50),
@un varchar(50),
@PageNumber int,
@PageSize int
AS
DECLARE @start_row int
DECLARE @end_row int
SET @end_row = @PageNumber * @PageSize
SET @start_row = @end_row - (@PageSize - 1)
BEGIN
WITH FRIENDS AS (
SELECT t.friend
FROM FRIEND_BLOCKED_LIST t
WHERE t.un = @un
AND t.subdomain = @subdomain
AND t.approved = 1
AND t.is_blocked = 0
UNION ALL
SELECT t.un as friend
FROM FRIEND_BLOCKED_LIST t
WHERE t.friend = @un
AND t.subdomain = @subdomain
AND t.approved = 1
AND t.is_blocked = 0)
SELECT t.friend
FROM (SELECT f.friend,
ROW_NUMBER() OVER (ORDER BY f.friend) AS rownum
FROM FRIENDS f
GROUP BY f.friend) t
WHERE t.rownum BETWEEN @start_row AND @end_row
END
如果您可以提供有关
FRIEND_BLOCKED_LIST
表的更多信息,则可以将查询更改为使用一个 CTE。 两个查询的 UNION
具有相同的 WHERE
子句,同时区分两列,这让我想知道是否不能写得更好。 FRIENDS CTE 可以重写为:
SELECT COALESCE(t.un, t.friend) as friend
FROM FRIEND_BLOCKED_LIST t
WHERE @un = COALESCE(t.un, t.friend)
AND t.subdomain = @subdomain
AND t.approved = 1
AND t.is_blocked = 0
将行号应用于要返回的列表:
WITH FRIENDS as
(
SELECT friend
FROM friend_blocked_list
WHERE un=@un and subdomain=@subdomain and approved=1 and is_blocked=0
UNION ALL
SELECT un as friend
FROM friend_blocked_list
WHERE friend=@un and subdomain=@subdomain and approved=1 and is_blocked=0 )
, recursive_friends as (
select friend
, row_number() over (order by friend asc) as rn
from FRIENDS )
select friend
from recursive_friends
where rn between @firstRow and @lastRow
order by FRIENDS.friend asc;