SQL Server 2008 R2 – lignes redondantes

La première requête

--645 rows SELECT * FROM ( SELECT DISTINCT cu.*, ROW_NUMBER() OVER ( ORDER BY cu.Id ) AS RowNum FROM Customers cu LEFT JOIN dbo.CustomerCategories cc ON cc.CustomerId = cu.Id LEFT JOIN dbo.CustomerServices cs ON cs.CustomerId = cu.Id WHERE ( @FullName IS NULL OR cu.FullName LIKE @FullName ) AND ( @CategoriesIdXml IS NULL OR cc.CategoryId IN ( SELECT * FROM @CategoriesList ) ) AND ( @ServicesIdXml IS NULL OR cs.ServiceId IN ( SELECT * FROM @ServicesList ) ) ) AS _ WHERE RowNum BETWEEN ( @PageIndex - 1 ) * @PageSize + 1 AND @PageIndex * @PageSize 

La deuxième requête

  --41 rows SELECT * FROM ( SELECT DISTINCT cu.*, ROW_NUMBER() OVER ( ORDER BY cu.Id ) AS RowNum FROM Customers cu -- LEFT JOIN dbo.CustomerCategories cc -- ON cc.CustomerId = cu.Id -- LEFT JOIN dbo.CustomerServices cs -- ON cs.CustomerId = cu.Id --WHERE ( @FullName IS NULL -- OR cu.FullName LIKE @FullName -- ) -- AND ( @CategoriesIdXml IS NULL -- OR cc.CategoryId IN ( SELECT * -- FROM @CategoriesList ) -- ) -- AND ( @ServicesIdXml IS NULL -- OR cs.ServiceId IN ( SELECT * -- FROM @ServicesList ) -- ) ) AS _ WHERE RowNum BETWEEN ( @PageIndex - 1 ) * @PageSize + 1 AND @PageIndex * @PageSize 

La deuxième requête renvoie le jeu de résultats correct (41 lignes), mais le premier renvoie 645 lignes, ce qui est incorrect. Mais j'utilise DISTINCT dans les deux requêtes et je me request pourquoi returnne d'abord trop de lignes.

Comment l'éviter?

ROW_NUMBER n'est pas correct, utilisez plutôt DENSE_RANK .

Vous pouvez voir la différence ici: Différence entre ROW_NUMBER, RANK et DENSE_RANK

ROW_NUMBER vous donnera un numéro différent pour le même client, et ce n'est pas ce que vous voulez, vous avez besoin de la même valeur pour que votre distinct puisse fonctionner.

Le DISTINCT est appliqué après la création du ROW_NUMBER ()

Comme ROW_NUMBER () est différent pour chaque ligne, chaque ligne est unique par définition. Cela signifie que vous semblez avoir quelques options.

Appliquez le Distinct dans une requête, puis enveloppez-en un autre autour de ROW_NUMBER ()

 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS row_num FROM ( SELECT DISTINCT cu.* FROM <your query> ) AS raw_data ) AS ordered_data WHERE RowNum BETWEEN ( @PageIndex - 1 ) * @PageSize + 1 AND @PageIndex * @PageSize 

Utilisez GROUP BY au lieu de DISTINCT

 SELECT * FROM ( SELECT DISTINCT cu.*, ROW_NUMBER() OVER (ORDER BY id) AS row_num FROM <your query> GROUP BY cu.id, cu.field1, cu.field2, etc, etc ) AS ordered_data WHERE RowNum BETWEEN ( @PageIndex - 1 ) * @PageSize + 1 AND @PageIndex * @PageSize