简体   繁体   中英

SQL Total Row Count (DENSE_RANK/DISTINCT)

I am selecting records that may contain duplicates, I need to be able to paginate a distinct result set.

At the moment, I have the following (simplified) query:

SELECT pagiWrapper.*  FROM (
    SELECT DISTINCT alias.id
    , alias.name
    , DENSE_RANK() OVER (ORDER BY alias.name ASC) AS 'paginationRowNo'
    , COUNT(*) OVER(PARTITION BY 1) AS 'paginationTotalRows' 
        FROM MyTable alias 
        LEFT JOIN MyTableTwo alias2 ON alias2.id = alias.id 
            WHERE ( /* condition */)
) pagiWrapper WHERE pagiWrapper.paginationRowNo > 0 AND pagiWrapper.paginationRowNo <= 15

There are 10 records in this result-set, however DISTINCT correctly returns 3, and DENSE_RANK correctly labels them 1 , 2 , and 3

My problem is paginationTotalRows still returns 10 (the original duplicates-included) result-set count, how can I modify the query so that paginationTotalRows returns the correct amount?

Try to find MAX(paginationRowNo) in the top query:

 SELECT pagiWrapper.*
      FROM(
           SELECT *, 
                 MAX(paginationRowNo) OVER(PARTITION BY 1) 
                    as 'paginationTotalRows'  
            FROM
             (           
              SELECT DISTINCT alias.id
               , alias.name
               , DENSE_RANK() OVER (ORDER BY alias.name ASC) AS 'paginationRowNo'
                  FROM MyTable alias 
                  LEFT JOIN MyTableTwo alias2 ON alias2.id = alias.id 
                     WHERE ( /* condition */)
              ) as PW
         ) pagiWrapper 
           WHERE pagiWrapper.paginationRowNo > 0 
                 AND pagiWrapper.paginationRowNo <= 15

Move the windowing function outside the select distinct . I would also suggest you use row_number() instead of dense_rank().

SELECT
      pagiWrapper.*
FROM (
            SELECT
                  iq.*
                , ROW_NUMBER() OVER (ORDER BY iq.name ASC) AS 'paginationRowNo'
                , COUNT(*) OVER (PARTITION BY 1)           AS 'paginationTotalRows'
            FROM (
                  SELECT DISTINCT
                        alias.id
                      , alias.name
                      , alias2.something_I_hope
                  FROM MyTable alias
                        LEFT JOIN MyTableTwo alias2
                                    ON alias2.id = alias.id
                  WHERE (1 = 1 /* condition */)
                  ) iq
      ) pagiWrapper
WHERE pagiWrapper.paginationRowNo > 0
      AND pagiWrapper.paginationRowNo <= 15

I recommend ROW_NUMBER() for pagination. This function cannot repeat a number within a partition and, if not partitioned it cannot repeat a number at all. DENSE_RANK() however can repeat a number within any partition and, if not partitioned can still repeat numbers. For pagination to be utterly predictable you need utterly predictable row numbering, so use ROW_NUMBER() . [please]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM