SQL не может ORDER BY до JOIN CTE.Альтернативы? - PullRequest
0 голосов
/ 23 октября 2018

SQL Server 2012, VS2015, SSMS 2017

У меня есть запрос, который в данный момент использует OUTER APPLY, который замедляет запрос.Я знаю, что мог бы ускорить его, изменив OUTER APPLY на LEFT JOIN ON, но OUTER APPLY использует ORDER BY для сортировки таблицы.JOIN не позволит мне использовать ORDER BY.Есть ли обходной путь для этого?

Текущий запрос:

SELECT 
    t1.ItemID,
    ISNULL(DATEDIFF(s, t1.localTimeStamp, t3.localTimeStamp),
    DATEDIFF(s, t1.localTimeStamp, @End)) AS Duration, 
    t1.localTimeStamp AS TimeStamp
FROM 
    CTE1 AS t1
OUTER APPLY 
    (SELECT TOP 1 localTimeStamp
     FROM CTE1 AS t2
     WHERE t2.localTimeStamp > t1.localTimeStamp AND t2.ItemID = t1.ItemID
     ORDER BY t2.localTimeStamp ASC) AS t3

Этот запрос по сути берет элемент и вычисляет продолжительность между записями таблицы для отдельных элементов.Исходной таблицей является CTE1, которая содержит строки с несколькими ItemID, Values ​​и localTimeStamps, которые не имеют определенного порядка.Я не мог использовать ORDER BY в предложении WITH CTE.

Новый запрос:

SELECT 
    t1.Value, t1.tName, t1.ItemID, 
    ISNULL(DATEDIFF(s, t1.localTimeStamp, t2.localTimeStamp),
    DATEDIFF(s, t1.localTimeStamp, @End)) AS Duration, 
    t1.localTimeStamp AS TimeStamp
FROM 
    CTE1 t1
LEFT JOIN 
    CTE1 t2 ON t2.localTimeStamp > t1.localTimeStamp AND t2.ItemID = t1.ItemID

Проблема в том, что он будет принимать ВСЕ строки с большими временными метками, а не только одну.это следующий (по порядку localTimeStamp не фактический номер строки).

Могу ли я получить Join to work или есть другой способ сделать это, который не замедляет запрос?

(Я знаю, что объединение происходит быстрее, потому что, хотя я объединяю значительно больше строк, этот второй запрос все еще превосходит первый.)

Поскольку я уверен, что это будет помечено как дублирующий вопрос, я хочу отметить, чтоЯ читал много других подобных вопросов на этом сайте об этом, и каждый, кто просит заказать предложение объединения, присоединяется к column1 = column2, где порядок не имеет значения, они просто ошиблись.поскольку я присоединяюсь к column1> column2, порядок действительно имеет значение.возможно, решение в том, что я должен использовать external apply, но этот вопрос НЕ задавался здесь раньше.

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Почему бы просто не использовать lead()?

SELECT tt.ItemID,
       COALESCE(DATEDIFF(second, t.localTimeStamp, LEAD(t.localTimeStamp) OVER (PARTITION BY t.ItemId ORDER BY t.localTimeStamp)),
                DATEDIFF(second, t.localTimeStamp, @End)
               ) as Duration, 
       t.localTimeStamp as TimeStamp
FROM CTE1 t;

Microsoft проделала хорошую работу по оптимизации APPLY.Я полагаю, что проблема с производительностью - запуск CTE дважды, который lead() должен исправить.

0 голосов
/ 23 октября 2018

Измените ваш второй запрос, чтобы использовать

Min (t2.localtimestamp) и группировать по остальным столбцам

...