Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 CROSS APPLY запрос, сокращение времени выполнения  [new]
MoonGuard
Member

Откуда:
Сообщений: 3
Есть таблица:
UserInfo
С такими полями:
UserInfo.Id
UserInfo.ComletedDate
UserInfo.logActionId

И есть вторая таблица:
Response
С такими полями:
Response.Id
Response.CreationDate
Response.logActionId

По факту, мне надо посчитать сколько записей будет во второй таблице до ComletedDate и после. Поле для объединения logActionId.
Составлял такой запрос (вариант 1):
+
Select *
FROM UserInfo userInfo
CROSS APPLY(	
		SELECT
		distinct resp.[logActionId] vacs
		,SUM(case when resp.CreationDate< userInfo.ComletedDate then 1 end) OVER(PARTITION BY userInfo.logActionId) as CountBefore
		,SUM(case when resp.CreationDate>= userInfo.ComletedDate then 1 end) OVER(PARTITION BY userInfo.logActionId) as CountAfter
		FROM Response as resp
		Where resp.logActionId= userInfo.logActionId) countInfo


Вариант 2:
+
Select *
FROM UserInfo userInfo
	CROSS APPLY(	
		SELECT Count(*) as RespCount
		FROM Response as resp
		Where resp.CreationDate < userInfo.ComletedDate and resp.logActionId= userInfo.logActionId
		GROUP BY resp.[logActionId]) countBefore
	CROSS APPLY(	
		SELECT Count(*) as RespCount
		FROM Response as resp
		Where resp.CreationDate >= userInfo.ComletedDate and resp.logActionId= userInfo.logActionId
		GROUP BY resp.[logActionId]) countAfter
GO


Работает, но проблема в том, что выборки длятся около полутрачасов, и это долго. Пытаюсь сделать быстрее, но что-то мне больше варианты в голову не приходят.
21 ноя 16, 16:52    [19917254]     Ответить | Цитировать Сообщить модератору
 Re: CROSS APPLY запрос, сокращение времени выполнения  [new]
buser
Member

Откуда: Санкт-Петербург
Сообщений: 4537
MoonGuard, а зачем apply distinct и окно?
21 ноя 16, 17:04    [19917357]     Ответить | Цитировать Сообщить модератору
 Re: CROSS APPLY запрос, сокращение времени выполнения  [new]
MoonGuard
Member

Откуда:
Сообщений: 3
Вообще userInfo - это cte (который через With, он выполняется секунд 35).
distinct добавил, т.к. он мне из этого аплая возвращал много одинаковых строк. Ну т.е. там же селект vacs сначала идет, по факту он его и возвращает (а это список с дублирующей информацией).
21 ноя 16, 17:08    [19917379]     Ответить | Цитировать Сообщить модератору
 Re: CROSS APPLY запрос, сокращение времени выполнения  [new]
buser
Member

Откуда: Санкт-Петербург
Сообщений: 4537
buser, а... понятно...
21 ноя 16, 17:09    [19917386]     Ответить | Цитировать Сообщить модератору
 Re: CROSS APPLY запрос, сокращение времени выполнения  [new]
Sybex
Member

Откуда: Moscow
Сообщений: 110
Может быть я чего-то не понимаю, но зачем тут APPLY? Почему бы просто не склеить две таблицы?

;with UserInfo (Id, ComletedDate, logActionId)
as
(
    select 1, cast('20161121' as date), 1 union all
    select 2, cast('20161120' as date), 2
)
,Response (Id, CreationDate, logActionId)
as
(
    select 1, cast('20161119' as date), 1 union all
    select 2, cast('20161120' as date), 1 union all
    select 3, cast('20161121' as date), 1 union all
    select 4, cast('20161122' as date), 1 union all
    select 5, cast('20161123' as date), 1 union all
    select 6, cast('20161119' as date), 2 union all
    select 7, cast('20161120' as date), 2 union all
    select 8, cast('20161121' as date), 2 union all
    select 9, cast('20161122' as date), 2
)
,cte
as
(
SELECT UserInfo.Id
      ,UserInfo.ComletedDate
      ,UserInfo.logActionId
      ,case when resp.CreationDate< userInfo.ComletedDate then 1 end as Before
      ,case when resp.CreationDate>= userInfo.ComletedDate then 1 end as [After]
  FROM UserInfo
       JOIN Response as resp ON UserInfo.logActionId = resp.logActionId
)
SELECT Id
      ,ComletedDate
      ,logActionId
      ,SUM(Before)  AS CountBefore
      ,SUM([After]) AS CountAfter
  FROM cte
 GROUP BY Id, ComletedDate, logActionId


А если в UserInfo приходят дубли, то их отрезать DISTINCT'ом ещё в том же CTE, ну или ещё одно сделать. Короче DISTINCT до склейки со второй таблицей чтобы был.
21 ноя 16, 17:26    [19917524]     Ответить | Цитировать Сообщить модератору
 Re: CROSS APPLY запрос, сокращение времени выполнения  [new]
aleks2
Guest
1. Это канешно здорово, что ты выучил кляузу OVER... но совершенно не следует пихать ее в каждую дырку.
2. distinct - это не панацея, но неиллюзорный тормоз. И нужен он те, яко мертвому припарка

Select *
FROM UserInfo userInfo
CROSS APPLY(	
		SELECT
		 SUM(case when resp.CreationDate< userInfo.ComletedDate then 1 end) 
		,SUM(case when resp.CreationDate>= userInfo.ComletedDate then 1 end)  as CountAfter
		FROM Response as resp
		Where resp.logActionId= userInfo.logActionId) countInfo


+ index on Response (logActionId, CreationDate)

это фсе, что можно тут сделать.

Радикальнее - надо перепроектировать этот бред.

ЗЫ. Ну еще если разве userInfo.ComletedDate для всех юзеров одна - можно crosss apply похерить.
21 ноя 16, 17:29    [19917539]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить