Sql server 2008 r2 - 冗余行

时间:2011-07-28 09:08:12

标签: sql-server sql-server-2008-r2

第一个查询

   --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

第二个查询

 --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

第二个查询返回正确的结果集(41行),但第一个返回645行是错误的。但我在两个查询中使用DISTINCT,我想知道为什么第一次返回太多行。

我该如何避免呢?

2 个答案:

答案 0 :(得分:3)

在创建ROW_NUMBER()之后正在应用DISTINCT

由于ROW_NUMBER()对于每一行都不同,因此根据定义,每一行都是唯一的。这意味着您似乎有几个选项。

在一个查询中应用Distinct,然后在其周围换一个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

使用GROUP BY代替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

答案 1 :(得分:1)

ROW_NUMBER不对,请改用DENSE_RANK

您可以在此处看到不同之处:Difference between ROW_NUMBER, RANK and DENSE_RANK

ROW_NUMBER会为同一个客户提供不同的号码,这不是您想要的,您需要相同的价值,以便您的分离能够发挥作用。