SQL-запрос - странное поведение - PullRequest
1 голос
/ 06 июня 2011
DECLARE @OrdersTemp TABLE
(
   OrderId UNIQUEIDENTIFIER
)

INSERT INTO @OrdersTemp
  SELECT ord.Id
  FROM Orders 

--all rows count
SELECT  
    @RowsCount = COUNT(DISTINCT ord.Id)
FROM   Orders 


--@RowsCount = 5. It's right!

--second table with paging
DECLARE @OrdersTempWithPaging TABLE
(
    OrderId UNIQUEIDENTIFIER
)

INSERT INTO @OrdersTempWithPaging
   SELECT OrderId
   FROM  (SELECT DISTINCT OrderId,
                 ROW_NUMBER() OVER (ORDER BY OrderId) AS RowNum
          FROM @OrdersTemp) AS alias
          WHERE 
              RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1
                     AND @PageIndex * @PageSize

SELECT * FROM @OrdersTempWithPaging
--10 or more rows. It's wrong.

Почему @OrdersTempWithPaging возвращает неправильное количество строк?Как мне этого избежать?

ОБНОВЛЕНИЕ : приведенный ниже оператор возвращает 25 = 5 * 5 строк (вместо 5)

   INSERT  INTO @OrdersTempWithPaging
                SELECT    OrderId
                FROM    (
                          SELECT    OrderId,
                                    ROW_NUMBER() OVER (ORDER BY OrderId ) AS RowNum
                          FROM      @OrdersTemp ) AS alias
                --WHERE   RowNum BETWEEN ( @PageIndex - 1 ) * @PageSize + 1
                             --  AND     @PageIndex * @PageSize
  SELECT * FROM @OrdersTempWithPaging

Ответы [ 3 ]

3 голосов
/ 06 июня 2011

Это потому, что ваш заказ внутри выбора,

 SELECT    DISTINCT OrderId,
           ROW_NUMBER() OVER (ORDER BY OrderId ) AS RowNumber

Вы должны выбрать заказ по столбцу, где вам не нужно использовать DISTINCT в выборе.

 SELECT    OrderId,
           ROW_NUMBER() OVER (ORDER BY OrderId ) AS RowNumber

Попробуй, без DISTINCT

2 голосов
/ 06 июня 2011

Попробуйте это (в обратном порядке использовать DISTINCT):

INSERT INTO @OrdersTempWithPaging
   SELECT DISTINCT OrderId
   FROM  (SELECT OrderId,
                 ROW_NUMBER() OVER (ORDER BY OrderId) AS RowNum
          FROM @OrdersTemp) AS alias
   WHERE 
       RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1
              AND @PageIndex * @PageSize

Если вам нужны только отдельные идентификаторы заказа, вы можете получить:

INSERT INTO @OrdersTemp
  SELECT DISTINCT ord.Id
  FROM Orders 

и затем:

INSERT INTO @OrdersTempWithPaging
   SELECT OrderId
   FROM  (SELECT OrderId,
                 ROW_NUMBER() OVER (ORDER BY OrderId) AS RowNum
          FROM @OrdersTemp) AS alias
   WHERE 
       RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1
              AND @PageIndex * @PageSize
0 голосов
/ 06 июня 2011

Вместо

SELECT DISTINCT OrderId,
       ROW_NUMBER() OVER (ORDER BY OrderId) AS RowNum
FROM @OrdersTemp

используйте

SELECT OrderId,
       ROW_NUMBER() OVER (ORDER BY OrderId) AS RowNum
FROM @OrdersTemp
GROUP BY OrderId

Это интересный случай другого различия между SELECT DISTINCT и SELECT GROUP BY, который проявляется, когда список выбора включает функцию ранжирования.

В первом запросе выходные данные содержат дубликаты OrderId значений от @OrdersTemp, поскольку функция ранжирования оценивается до DISTINCT применяется.Напротив, второй запрос сначала группирует строки по OrderId (т.е. эффективно выбирает сначала отдельные значения OrderId), а затем применяет ранжирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...