【问题标题】:Sql server 2008 r2 - redundant rowsSql server 2008 r2 - 冗余行
【发布时间】:2011-07-28 09:08:12
【问题描述】:

第一个查询

   --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,我想知道为什么首先返回太多行。

如何避免?

【问题讨论】:

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


    【解决方案1】:

    在创建 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
    

    【讨论】:

      【解决方案2】:

      ROW_NUMBER 不对,改用DENSE_RANK。

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

      ROW_NUMBER 将为同一客户提供不同的编号,这不是您想要的,您需要相同的值才能使您的 distinct 起作用。

      【讨论】:

      • 也许吧。 RANK()函数返回41行,但分页不正常!
      • 你试过什么? Rank 会搞砸你的分页,但 Dense_Rank 一定是好的。
      • 但是 dance_rank() 工作正常!很好。是否真的因为使用 ROW_NUMBER 而不是 DENSE_RANK 而发生?
      • @Alex: ROW_NUMBER() 为 645 行中的每一行提供一个唯一的 rownum,并且 THEN 正在应用 DISTINCT。 ROW_NUMBER() 然后 DISTINCT 的顺序在这里完全重要。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 2013-02-07
      相关资源
      最近更新 更多