2014-10-16 2 views
0

Я пытаюсь заказать записи по 3 столбцам, а затем выбрать конкретный идентификатор и запись до этого плюс строку после этого. Вот мой вопрос:Эффективный способ написать этот запрос

;With Cte As 
(
    SELECT ROW_NUMBER() Over(Order By Book, PageINT, [IDAuto]) as RowNum, [IdAuto] 

     FROM CCWiseInstr2 
) 
Select * From Cte 
    Where RowNum = (Select RowNum From Cte 
    Where IdAuto = 211079) 
     UNION 
Select * From Cte 
    Where RowNum = (Select RowNum - 1 From Cte 
    Where IdAuto = 211079) 
    UNION 
Select * From Cte 
    Where RowNum = (Select RowNum + 1 From Cte 
    Where IdAuto = 211079) 

Что мог бы другой эффективный способ написать этот запрос. На данный момент запрос занимает около 336 ms после создания всех индексов, которые выглядят немного выше для меня.

Вот план для запроса:

http://gyazo.com/9a7f1c37d4433665d0949acf03c4561c

Любая помощь приветствуется.

+0

Какая версия SQL Server? У вас есть индекс на IDAuto? –

+0

Sql server 2012 с тегом в вопросе. Да IDAuto - это кластеризованный индекс. –

+0

И у меня есть некластеризованный индекс на (Book, PageINT, IDAuto) как 1 индекс. У меня около 0,4 миллиона строк в таблице. –

ответ

2

Как об этом запросе:

;With Cte As 
(
    SELECT ROW_NUMBER() Over(Order By Book, PageINT, [IDAuto]) as RowNum, [IdAuto]  
     FROM CCWiseInstr2 
) 
Select RowNum, IDAuto From Cte 
    Where RowNum IN ( 
     Select RowNumber From 
      (
       Select RowNum - 1 as RowNumPrev, 
         RowNum as RowNum, 
         RowNum + 1 as RowNumNext 
         From Cte 
          Where IdAuto = 211079 
      ) vw unpivot ( 
          RowNumber For 
            IdAuto IN (RowNumPrev, RowNum, RowNumNext) 
         ) unpw) 

Вместо UNION просто использовать UNPIVOT, который будет преобразовывать столбцы в строки, которые вы могли бы использовать в IN , Дайте мне знать, как это происходит.

+0

Отлично. Это потребовало ** 146 мс **. Значительное улучшение! –

2

Вы можете использовать функции LEAD и LAG с SQL Server. Вот отличная статья о Simple Talk, охватывающая все варианты. (Код ниже непроверенные)

https://www.simple-talk.com/sql/t-sql-programming/sql-server-2012-window-function-basics/

SELECT 
    [IdAuto], 
    LAG([IDAuto], 1) OVER(Order By Book, PageINT, [IDAuto]) AS PreviousSale, 
    LEAD([IDAuto], 1) OVER(Order By Book, PageINT, [IDAuto]) AS NextSale 
FROM 
    CCWiseInstr2 
WHERE [IdAuto] = 211079; 
+0

я должен был изменить свой запрос на 'Select * From ( \t ВЫБРАТЬ \t [IdAuto], \t LAG ([IDAuto], 1) OVER (Order By Book, PageINT, [IDAuto]) AS PreviousSale, \t LEAD ([IDAuto], 1) OVER (Заказывайте книги, PageINT, [IDAuto]) AS NextSale \t ИЗ \t CCWiseInstr2 ) Vw Где vw.IdAuto = 211079' в противном случае я бы получить NULL в качестве previousSale и NextSale и если я измените его на то, что это намного медленнее занимает около 1,2 секунды. Это в 3,5 раза медленнее, чем моя оригинальная версия. –

+0

У меня нет указаний на размеры столбцов, мощность данных или объем строк, поэтому ваш row_number над таблицей может работать достаточно хорошо, но LEAD и LAG - это функции, реализованные для выполнения именно того, что вы пытаетесь сделать. Тем не менее, я не тестировал код, прежде чем писать, но вместо этого попытался проиллюстрировать, как вы можете его использовать. – Vinnie

Смежные вопросы