Медленный запрос, получающий максимальную и минимальную дату из таблицы на основе статуса - PullRequest
2 голосов
/ 26 июня 2019

У меня есть следующие данные, где мне нужно получить минимальную начальную дату и максимальную конечную дату в зависимости от пользователя и его статуса. Запрос сработал, но для его выполнения требуется более 55 минут. Есть ли способ, которым я могу написать это эффективно? в таблице около 150 000 пользователей

Данные

DECLARE @TBL TABLE (Users INT,  Users_Status VARCHAR(5),    [Start_Date] DATE,  End_Date DATE)
INSERT INTO @TBL VALUES
(1,'A','2019-03-07','2019-03-22'),(1,'A','2019-01-04','2019-01-08'),(1,'A','2019-01-12','2019-01-27'),
(1,'B','2019-01-30','2019-02-02'),(1,'B','2019-02-27','2019-03-13'),(1,'B','2019-01-13','2019-01-24'),
(2,'A','2019-03-15','2019-03-28'),(2,'A','2019-05-19','2019-05-27'),(3,'A','2019-05-31','2019-06-04'),
(3,'A','2019-05-18','2019-06-03'),(3,'A','2019-01-12','2019-01-13'),(3,'A','2019-04-12','2019-05-02'),
(3,'B','2019-01-08','2019-01-18'),(3,'B','2019-04-16','2019-04-18'),(4,'B','2019-05-25','2019-06-03'),
(5,'A','2019-03-26','2019-03-30'),(5,'A','2019-06-13','2019-06-26'),(5,'A','2019-02-02','2019-02-18'),
(5,'B','2019-01-17','2019-01-20'),(5,'B','2019-03-30','2019-04-19'),(5,'B','2019-05-04','2019-05-16'),
(5,'B','2019-03-25','2019-04-10'),(5,'B','2019-03-09','2019-03-27')

Я пробовал этот запрос

;WITH StartEnd AS
(SELECT
*
,ROW_NUMBER()OVER(PARTITION BY  Users,Users_Status   ORDER BY [Start_Date] ASC) AS Utart
,ROW_NUMBER()OVER(PARTITION BY  Users,Users_Status  ORDER BY End_Date DESC) AS UEnd
FROM @TBL
) ,Starts AS
(
SELECT
*
FROM StartEnd
WHERE Utart =1
), 
Ends AS
(
SELECT
*
FROM StartEnd
WHERE UEnd =1
)
SELECT distinct
 S.*
 ,(SELECT MIN(ST.[Start_Date]) FROM Starts ST WHERE ST.Users = S.Users AND ST.Users_Status =S.Users_Status ) AS Min_Start_Date
 ,(SELECT MAX(e.End_Date) FROM Ends E WHERE E.Users = S.Users AND E.Users_Status =S.Users_Status ) AS  Max_end_Date
FROM StartEnd S

Токовый выход

enter image description here

Желаемый вывод

enter image description here

Ответы [ 2 ]

1 голос
/ 26 июня 2019

Я считаю, что ваш запрос может быть упрощен до

SELECT Users, 
    Users_Status,
    Start_date,
    End_Date,
    MIN(Start_Date) OVER (PARTITION BY Users, Users_Status) Min_Start_Date,
    MAX(End_Date) OVER (PARTITION BY Users, Users_Status) Max_End_Date
FROM @tbl

Однако производительность, скорее всего, снизится до индексации

1 голос
/ 26 июня 2019

Первое, что нужно сделать для повышения производительности запросов, - убедиться, что на месте есть необходимые индексы. Попробуйте посмотреть план выполнения запроса:

  1. Нажатие кнопки «Показать фактический план выполнения» в SSMS перед выполнением запроса (сочетание клавиш Ctrl + M)
  2. Просмотрите примерный план выполнения запроса в SQL Server Management Studio, нажав кнопку «Показать примерный план выполнения» в SSMS (сочетание клавиш Ctrl + L).

Показать приблизительный план выполнения Кнопка в SSMS

Затем добавьте любые предлагаемые индексы в план выполнения. Предлагаемые индексы будут выделены зеленым цветом. Вы можете щелкнуть правой кнопкой мыши и выбрать «Отсутствующие детали индекса», чтобы получить скрипт создания индекса в новом окне. Измените его по мере необходимости перед запуском.

План выполнения в SSMS

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