views:

89

answers:

6
+1  Q: 

Paging in T-SQL

I am trying to implement paging using Row_Number() method in this query but with no luck.

The following Query uses recursive way to get Sites for a set of categories.

    WITH hierarchy AS (
  SELECT yt.id

    FROM [dbo].[TH_Categories] yt
   WHERE yt.ID = @topicID And CultureID = @cultureID 
  UNION ALL
  SELECT yt.id

    FROM [dbo].[TH_Categories] yt
    JOIN hierarchy h ON h.ID = yt.ParentCategoryID)
    Select id, [SiteName]
      ,[SiteURL]
      ,[Description]
      ,[Logo]
      ,[CultureID]
      ,[DateAdded],  dbo.GetSiteFollowers(id) AS Followers from dbo.TH_Sites where id in (
 Select Distinct SiteID from dbo.TH_CategoryFeeds Where CatID in (
   SELECT ID
    FROM hierarchy t   ))

This query returns all the sites for a set of categories. I am trying to integrate Row_Number() to the dbo.TH_Sites table so I can get x number of records for each request using the

Where RowNumber BETWEEN @rowStart AND @rowEnd

But I keep getting T-SQL errors.

Any tips guys, thanks.

I am trying this :

    WITH hierarchy AS (
  SELECT yt.id

    FROM [dbo].[TH_Categories] yt
   WHERE yt.ID = @topicID And CultureID = @cultureID 
  UNION ALL
  SELECT yt.id

    FROM [dbo].[TH_Categories] yt
    JOIN hierarchy h ON h.ID = yt.ParentCategoryID)

    Select id, [SiteName]
      ,[SiteURL]
      ,[Description]
      ,[Logo]
      ,[CultureID]
      ,[DateAdded], ROW_NUMBER() OVER (order by [DateAdded] DESC) AS 'RowNumber' ,  dbo.GetSiteFollowers(id) AS Followers from dbo.TH_Sites where RowNumber = 5  AND  id in (
 Select Distinct SiteID from dbo.TH_CategoryFeeds Where CatID in (
   SELECT ID
    FROM hierarchy t)) 

But I am getting RowNumber is not a valid column

Here is another Implementation :

WITH hierarchy AS (

SELECT yt.id

FROM [dbo].[TH_Categories] yt

WHERE yt.ID = @topicID And CultureID = @cultureID UNION ALL SELECT yt.id

FROM [dbo].[TH_Categories] yt
JOIN hierarchy h ON h.ID = yt.ParentCategoryID)
WITH numbered_hierarchy AS (
Select id, [SiteName]
  ,[SiteURL]
  ,[Description]
  ,[Logo]
  ,[CultureID]
  ,[DateAdded] , ROW_NUMBER() OVER (order by [DateAdded] DESC) AS 'RowNumber',  dbo.GetSiteFollowers(id) AS Followers from dbo.TH_Sites where  id in (

Select Distinct SiteID from dbo.TH_CategoryFeeds Where CatID in ( SELECT ID FROM hierarchy t )) )

 SELECT id
     , [SiteName]
     , [SiteURL]
     , [Description]
     , [Logo]
     , [CultureID]
     , [DateAdded]
     , RowNumber
     , Followers
FROM numbered_hierarchy
WHERE RowNumber BETWEEN 1 AND 5
+3  A: 

You need to put the ROW_NUMBER() function into your CTE:

WITH YourCTE AS
(
   SELECT (list of fields),
          ROW_NUMBER() OVER(ORDER BY ......) AS 'RowNum'
) 
SELECT (list of fields), RowNum
FROM YourCTE

Once you do that, you can easily select certain rows from the CTE:

WITH YourCTE AS
(
   SELECT (list of fields),
          ROW_NUMBER() OVER(ORDER BY ......) AS 'RowNum'
) 
SELECT (list of fields), RowNum
FROM YourCTE
WHERE RowNum BETWEEN 51 AND 75  -- or something like that

Not sure how that'll work with recursive CTE's though (I don't have SQL Server at hand right now to test this).

marc_s
The paging is at the level of a nested table called dbo.TH_Sites.
Joseph Ghassan
+2  A: 

SQL doesn't allow the use of column aliases in a WHERE clause. Instead, put the RowNumber calculation into your CTE:

WITH numbered_rows AS (
    SELECT s.id
         , s.[SiteName]
         , s.[SiteURL]
         , s.[Description]
         , s.[Logo]
         , s.[CultureID]
         , s.[DateAdded]
         , ROW_NUMBER() OVER (order by s.[DateAdded] DESC) AS [RowNumber]
         , dbo.GetSiteFollowers(s.id) AS [Followers]
    FROM dbo.TH_Sites s
    INNER JOIN (
        SELECT DISTINCT SiteID
        FROM dbo.TH_CategoryFeeds cf
        INNER JOIN dbo.TH_Categories c ON c.ID = cf.CatID
        WHERE (c.ID = @topicID OR c.ParentCategoryID = @topicID)
            AND c.CultureID = @cultureID
    ) feeds ON feeds.SiteID = s.ID
)

SELECT id
     , [SiteName]
     , [SiteURL]
     , [Description]
     , [Logo]
     , [CultureID]
     , [DateAdded]
     , RowNumber
     , Followers
FROM numbered_rows
WHERE RowNumber BETWEEN @rowStart AND @rowEnd

EDIT: Eliminated the hierarchy CTE.

EDIT: Modified the JOINs to use a sub-query.

In addition, you could probably get away with using JOINs instead of WHERE...IN.
When I hook up another CTE to the query I get this error : Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Joseph Ghassan
@Joseph - You comma delimit them. e.g. `;With tl as (select...), t2 as (select...) select * from t1 join t2...`
Martin Smith
Sorry jeff, but can u modify the query u've post it so I can have an idea what u intend to do. thanks for the help.
Joseph Ghassan
@Joseph: Oops. Don't know quite what I was thinking there. See my edits.
Thanks Jeff for your help. But I am getting the redundant data. The first query I wrote in my post returns the correct number of Sites which are 53. Now your query returns 36 with duplicates sites.hmmm, Seems it is tough to solve.
Joseph Ghassan
@Joseph: I modified the CTE to use a sub-query for the relationship between feeds and categories. Does that work?
RowNumber works perfectly but I am getting only 16 Rows where the Category 45 has 56 Sites. But the RowNumber works correctly.
Joseph Ghassan
When I mean Category 45 has 56 sites that means 45 and all its descendant ( all Cats that has ParentCategoryID = 45 and so on ).
Joseph Ghassan
A: 

Edited: Added the distinct in the final select incase the join to cte was giving multiple records.

Try this, I think its what your going for.

;with hierarchy 
as
(
    select 
        yt.id

    from 
        dbo.TH_Categories yt

    where 
        yt.ID = @topicID 
        and CultureID = @cultureID 

    union

    select 
        parent.id as id

    from 
        dbo.TH_Categories yt
        left join dbo.th_categories parent
            on yt.id = parent.parentcategoryid
    order by dateadded desc
)

select distinct
    ths.id 
    ,ths.[SiteName]
    ,ths.[SiteURL]
    ,ths.[Description]
    ,ths.[Logo]
    ,ths.[CultureID]
    ,ths.[DateAdded],  
    dbo.GetSiteFollowers(ths.id) AS Followers 

from 
    dbo.TH_Sites ths
    join dbo.TH_CategoryFeeds cf
        on ths.id = cf.siteid
    join 
        (
            select
                id
                ,row_number() as RowNumber
            from
                hierarchy 
        ) h on cf.catid = h.id

where
    h.rownumber = 5;
It is close, but I am getting for rownumber = 5 6 records.so it is not accurate.
Joseph Ghassan
RowNumber Between 1 and 5 is getting 16 Rows.
Joseph Ghassan
I added a distinct on to the final select in case the category feeds is giving multiple records on the join. Not sure of your table scema.
Sorry, but the query is broken. with distinct it is getting 4 rows whatever the rownumber is
Joseph Ghassan
A: 

This query returns all the sites :

WITH hierarchy AS (

SELECT yt.id

FROM [dbo].[TH_Categories] yt

WHERE yt.ID = @topicID And CultureID = @cultureID UNION ALL SELECT yt.id

FROM [dbo].[TH_Categories] yt
JOIN hierarchy h ON h.ID = yt.ParentCategoryID)

Select id, [SiteName]
  ,[SiteURL]
  ,[Description]
  ,[Logo]
  ,[CultureID]
  ,[DateAdded], dbo.GetSiteFollowers(id) AS Followers from dbo.TH_Sites where  id in (

Select Distinct SiteID from dbo.TH_CategoryFeeds Where CatID in ( SELECT ID FROM hierarchy t ))

I just need to implement paging to this query. is it that difficult ?

Come on T-SQL GURUS !!!!!

Joseph Ghassan
A: 
WITH hierarchy AS
(
    SELECT yt.id
    FROM [dbo].[TH_Categories] yt
    WHERE yt.ID = @topicID AND CultureID = @cultureID

    UNION ALL

    SELECT yt.id
    FROM [dbo].[TH_Categories] yt
    JOIN hierarchy h ON h.ID = yt.ParentCategoryID
)
SELECT id
    , [SiteName]
    , [SiteURL]
    , [Description]
    , [Logo]
    , [CultureID]
    , [DateAdded]
    , dbo.GetSiteFollowers(id) AS Followers
FROM dbo.TH_Sites
WHERE id in
(
    SELECT DISTINCT SiteID
    FROM dbo.TH_CategoryFeeds
    WHERE CatID IN ( SELECT ID FROM hierarchy t )
)
AND ROW_NUMBER() OVER (ORDER BY [DateAdded] DESC) BETWEEN @rowStart AND @rowEnd
ORDER BY [DateAdded] DESC
I am getting this :Windowed functions can only appear in the SELECT or ORDER BY clauses.
Joseph Ghassan
Jeff, it is a tough Coconut :)
Joseph Ghassan
Yes, it is, and I'm out of ideas. :(
It is ok man. I will see what I can do. Thanks a bunch !
Joseph Ghassan
A: 
;WITH hierarchy AS 
(
     SELECT yt.id    
       FROM [dbo].[TH_Categories] yt
      WHERE yt.ID = @topicID And CultureID = @cultureID
     UNION ALL
     SELECT yt.id    
       FROM [dbo].[TH_Categories] yt
       JOIN hierarchy h ON h.ID = yt.ParentCategoryID
)
, YourRows AS 
(
    Select id, 
           [SiteName]
          ,[SiteURL]
          ,[Description]
          ,[Logo]
          ,[CultureID]
          ,[DateAdded]
          ,dbo.GetSiteFollowers(id) AS Followers 
          ,ROW_NUMBER() OVER (ORDER BY [DateAdded] DESC) AS RowNumber
     from dbo.TH_Sites 
    where id in (Select Distinct SiteID 
                   from dbo.TH_CategoryFeeds 
                  Where CatID in (SELECT ID
                                    FROM hierarchy t ))
)
SELECT * FROM YourRows 
WHERE RowNumber>=@rowStart and RowNumber<=@rowEnd
Joseph Ghassan