Оптимизируйте запрос с помощью самостоятельных объединений и групповых предложений в предложении where - PullRequest
0 голосов
/ 15 марта 2019

Это мой старый запрос:

Select AccountID,AccountDesc,
    CASE 
    WHEN NOT EXISTS (select AccountID from #B where #B.AccountID = P1.AccountID) THEN cast(cast(GETDATE() as date) as varchar)     
    ELSE cast(cast(CreateDate as date) as varchar)
    END 
    FROM #A P1
    WHERE P1.EndDate = (Select max(EndDate) from #A P2 where P1.AccountID = P2.AccountID and P2.Categ1 = 'F'
    group by P2.AccountID) 
    and P1.StartDate = (Select max(StartDate) from #A P2 where P1.AccountID = P2.AccountID and P2.Categ1 = 'F'
    group by P2.AccountID) 
    and P1.CreateDate = (Select max(CreateDate ) from #A P2 where P1.AccountID = P2.AccountID and P2.Categ1 = 'F'
    group by P2.AccountID) 
    and P1.NewStartDate= (Select max(NewStartDate) from #A P2 where P1.AccountID = P2.AccountID and P2.Categ1 = 'F'
    group by P2.AccountID)

Я хотел избавиться от повторяющихся самосоединений и групповых байтов в предложении where, поэтому я избавился от части "Category1 = F" ивместо этого добавьте его в рабочую таблицу, где вместо этого я добавляю предложение.И я подумал, что самообъединение предназначено только для получения значений MAX, поэтому, поскольку я составил рабочий стол, я не думал, что мне понадобятся эти самообъединения.Итак, я получаю этот новый запрос:

Select AccountID,AccountDesc,
    CASE 
    WHEN NOT EXISTS (select AccountID from #B where #B.AccountID = P1.AccountID) THEN cast(cast(GETDATE() as date) as varchar)     
    ELSE cast(cast(CreateDate as date) as varchar)
    END 
    FROM #A P1
    WHERE P1.EndDate = (Select max(EndDate) from #A)
    and P1.StartDate = (Select max(StartDate) from #A) 
    and P1.CreateDate = (Select max(CreateDate) from #A) 
    and P1.NewStartDate= (Select max(NewStartDate) from #A)

Но это не возвращает одинаковое количество записей, я полагаю, потому что я также удалил предложения «Группировать по» в условиях where?

Может ли кто-нибудь помочь мне сделать этот оригинальный запрос быстрее, но при этом вернуть те же результаты?

Ответы [ 3 ]

1 голос
/ 15 марта 2019

Для начала: все эти GROUP BY AccountID предложения в вашем запросе излишни, так как подзапросы всегда выбирают данные только для одного AccountID.

В предложении WHERE пробовано следующее:

WHERE (AccountID, EndDate, StartDate, CreateDate, NewStartDate) IN
(
  SELECT AccountID, MAX(EndDate), MAX(StartDate), MAX(CreateDate), MAX(NewStartDate)
  FROM #A
  WHERE Categ1 = 'F'
  GROUP BY AccountID
)

SQL Server, однако, не поддерживает этот синтаксис. Так что конвертируйте это в EXISTS:

WHERE EXISTS
(
  SELECT 1
  FROM #A P2
  WHERE P2.AccountID = P1.AccountID AND P2.Categ1 = 'F'
  HAVING P1.EndDate = MAX(P2.EndDate)
     AND P1.StartDate = MAX(P2.StartDate)
     AND P1.CreateDate = MAX(P2.CreateDate)
     AND P1.NewStartDate = MAX(P2.NewStartDate) 
)
0 голосов
/ 15 марта 2019

Я верю, что это поможет вам

Select AccountID,AccountDesc,
     CASE WHEN NOT EXISTS (select AccountID from #B where #B.AccountID = P1.AccountID) THEN cast(cast(GETDATE() as date) as varchar)     
     ELSE cast(cast(CreateDate as date) as varchar) END 
  FROM #A P1
    CROSS APPLY (
                  SELECT max(EndDate) EndDate, max(StartDate) StartDate, max(CreateDate ) CreateDate ,max(NewStartDate)NewStartDate 
                  FROM #A P2
                  WHERE P1.AccountID = P2.AccountID and P2.Categ1 = 'F'
                 ) AS P3
    WHERE P1.EndDate = P3.EndDate AND P1.StartDate = P3.StartDate
    AND P1.CreateDate = P3.CreateDate AND P1.NewStartDate = p3.NewStartDate
0 голосов
/ 15 марта 2019

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

;with cte as
(
select Account,max(EndDate) ED ,max(StartDate) SD,max(CreateDate ) CD ,max(NewStartDate) NSD 
from #a
where Categ1 = 'F'
group by Account
)
Select AccountID,AccountDesc,
    CASE 
    WHEN NOT EXISTS (select AccountID from #B where #B.AccountID = P1.AccountID) THEN cast(cast(GETDATE() as date) as varchar)     
    ELSE cast(cast(CreateDate as date) as varchar)
    END 
 FROM #A p1
     join cte on p1.Account=cte.Account
           and p1.StartDate=cte.SD
           and p1.EndDate = cte.ED
           and p1.CreateDate = cte.CD 
           and p1.NewStartDate=cte.NSD

вот еще одно улучшение:

CASE 
    WHEN NOT EXISTS (select AccountID from #B where #B.AccountID = P1.AccountID) THEN cast(cast(GETDATE() as date) as varchar)     
    ELSE cast(cast(CreateDate as date) as varchar)

можно изменить, присоединившись к #B.

;with cte as
(
select Account,max(EndDate) ED ,max(StartDate) SD,max(CreateDate ) CD ,max(NewStartDate) NSD 
from #a
where Categ1 = 'F'
group by Account
)
Select AccountID,AccountDesc,
    case when p2.Account is not null 
         then cast(CreateDate as varchar(10)) 
         else cast(cast(getdate() as date) as varchar(10)) end
 FROM #A p1
     join cte on p1.Account=cte.Account
           and p1.StartDate=cte.SD
           and p1.EndDate = cte.ED
           and p1.CreateDate = cte.CD 
           and p1.NewStartDate=cte.NSD
     left join #B p2 on p1.Account=p2.Account
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...