Row_number () возвращает нулевое значение, как решить эту неожиданную проблему - PullRequest
0 голосов
/ 20 декабря 2018

Здесь SQL-запрос

;WITH rankedresults AS 
(
    SELECT 
        userid, 
        rowid 
    FROM   
        (SELECT 
             userid, 
             ROW_NUMBER() OVER (ORDER BY referredplayercount DESC) AS RowId 
         FROM   
             tblusersprofile) dt 
    WHERE  
         rowid BETWEEN 1 AND 50
) 
SELECT 
    tblusersprofile.userid, 
    referredplayercount, 
    username, 
    avatarimagelink, 
    authoritylevel, 
    rowid 
FROM
    tblusersprofile 
LEFT JOIN 
    rankedresults ON tblusersprofile.userid = rankedresults.userid 
WHERE  
    tblusersprofile.userid IN (SELECT rankedresults.userid 
                               FROM rankedresults) 
    AND referredplayercount > 0 
ORDER BY 
    rowid ASC 

Здесь возвращаемые результаты, которые, как ожидается, не будут иметь нулевого номера строки

enter image description here

Интересно, что rankedresults заново сгенерировано с этим запросом?

SELECT rankedresults.userid 
FROM rankedresults

1 Ответ

0 голосов
/ 20 декабря 2018

ИД пользователя 1137 находится только в таблице tbluserprofile, а не в CTE ранжированных результатов.

Поскольку это LEFT JOIN, так как совпадений нет, rowid в результате отображается как NULL.

Функция row_number () сама по себе не может генерировать значения NULL.

Но чтобы убедиться, что ROW_NUMBER в CTE всегда возвращает один и тот же порядок, добавьте идентификатор пользователя в ORDER BY

ROW_NUMBER() OVER (ORDER BY referredplayercount DESC, userid) AS RowId

Но, возможно, вы могли бы избежать использования этого CTE дважды?

;WITH rankedresults AS 
(
    SELECT 
     userid, 
     RowId
    FROM
    (
       SELECT 
        userid, 
        ROW_NUMBER() OVER (ORDER BY referredplayercount DESC, userid ASC) AS RowId 
       FROM tblusersprofile
       WHERE referredplayercount > 0 
    ) dt
    WHERE RowId BETWEEN 1 AND 50
) 
SELECT 
    usrprof.userid, 
    usrprof.referredplayercount, 
    usrprof.username, 
    usrprof.avatarimagelink, 
    usrprof.authoritylevel, 
    rr.rowid 
FROM
    tblusersprofile usrprof
JOIN 
    rankedresults rr ON rr.userid = usrprof.userid
ORDER BY 
    rr.RowId ASC

И если вы можете использовать OFFSET & FETCH , и вам не нужен этот RowId в select?
Тогда вам может даже не понадобиться CTE с row_numberчтобы отобразить результаты.

declare @offsetrows int = 0;
declare @nextrows int = 50;

SELECT 
 userid, 
 referredplayercount, 
 username, 
 avatarimagelink, 
 authoritylevel
FROM tblusersprofile
WHERE referredplayercount > 0
ORDER BY referredplayercount DESC, userid ASC
OFFSET @offsetrows ROWS FETCH NEXT @nextrows ROWS ONLY;

Упрощенные тесты для db <> fiddle здесь

...