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

Откуда:
Сообщений: 6
Запрос выводит данные по карточкам звонков.
Table1 - таблица с данными по карточкам
Table2 - таблица с данными по звонкам
Сложный запрос и совсем не оптимизированный, я знаю, но дело не в этом.
Необходимо в данном запросе выводить данные только по последней дате поля t2.OfferedTime.
Вот как это выглядит сейчас:
Картинка с другого сайта.

а надо
Картинка с другого сайта.

сам запрос:
	SELECT  t1.date as 'Дата, время',
			t2.OfferedTime as 'время звонка',
			CAST(s.Call_ID as INT) as 'ID звонка',
			dbo.getagentloginfromid(dbo.getAgentIDfromCallID(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)) as 'ID оператора',		
	FROM Table2 t2
	JOIN Table1 t1
	ON (dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.SOT_CLIENT
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.SOT_CLIENT2
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.SOT_CLIENT3
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.DT_CLIENT
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.RT_CLIENT
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.DOP_NUM1
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.DOP_NUM2
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.KT_1
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.KT_2
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.KT_3)
			AND ABS(DATEDIFF(MI, t1.date_modified + 0.25, t2.OfferedTime))<=30
	WHERE t2.CallOut=1 AND dbo.getAgentIDfromCallID(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime) IN (SELECT Agent_ID FROM AgentConfiguration)
				AND (CAST(ROUND(CAST(t2.OfferedTime as float), 0, 1) as datetime)>= '2013-03-27'
				AND CAST(ROUND(CAST(t2.OfferedTime as float), 0, 1) as datetime)<= '2013-03-27')
	ORDER BY t2.OfferedTime ASC
27 мар 13, 08:41    [14099923]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Добрый Э - Эх
Guest
Читай, выбирай...
27 мар 13, 08:44    [14099930]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Rinatusss
Member

Откуда:
Сообщений: 6
Добрый Э - Эх,

Спасибо! Очень помогли!
28 мар 13, 15:21    [14107864]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Что-то мне подсказывает, что если уж от функции отказаться не получается, то вместо
ON (dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.SOT_CLIENT
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.SOT_CLIENT2
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.SOT_CLIENT3
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.DT_CLIENT
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.RT_CLIENT
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.DOP_NUM1
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.DOP_NUM2
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.KT_1
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.KT_2
		OR dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)=t1.KT_3)
лучше писать так:
ON (dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime) 
IN (t1.SOT_CLIENT, t1.SOT_CLIENT2, t1.SOT_CLIENT3, t1.DT_CLIENT, t1.RT_CLIENT, t1.DOP_NUM1, t1.DOP_NUM2, t1.KT_1, t1.KT_2, t1.KT_3))
Или функция по-любому будет вызвана 1 раз?
28 мар 13, 15:29    [14107950]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Cygapb-007,

Оптимизатор по-любому разложит выражение "X in (A, B, C)" на "X=A or X=B or X=C" и вызовет функцию N раз.
28 мар 13, 15:42    [14108065]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Cygapb-007
если уж от функции отказаться не получается, то вместо
...
лучше писать так:
...

А вообще, конечно, лучше — из соображений читабельности кода.
28 мар 13, 15:48    [14108128]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Гость333
Cygapb-007,

Оптимизатор по-любому разложит выражение "X in (A, B, C)" на "X=A or X=B or X=C" и вызовет функцию N раз.
то есть когда в аггрегировании пишется несколько раз COUNT(*) - он высчитывается каждый раз заново? Или аналогия не уместна:)?
Как-то не верится, что в любом случае будет вызываться N раз... А тестировать - чесслово лениво:)
28 мар 13, 16:26    [14108497]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Cygapb-007
то есть когда в аггрегировании пишется несколько раз COUNT(*) - он высчитывается каждый раз заново? Или аналогия не уместна:)?

В этом случае оптимизатор заменит COUNT(*) на что-то вроде [Expr1002] и будет проверять условие " [Expr1002] = A or [Expr1002] = B or [Expr1002] = C ".

Cygapb-007
Как-то не верится, что в любом случае будет вызываться N раз

Ну, может, и есть какой-то приём, позволяющий серверу "закэшировать" вычисленное значение пользовательской функции, но у меня сделать такое не получилось.
28 мар 13, 16:54    [14108724]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
Cygapb-007
Гость333
Cygapb-007,

Оптимизатор по-любому разложит выражение "X in (A, B, C)" на "X=A or X=B or X=C" и вызовет функцию N раз.
то есть когда в аггрегировании пишется несколько раз COUNT(*) - он высчитывается каждый раз заново? Или аналогия не уместна:)?
Как-то не верится, что в любом случае будет вызываться N раз... А тестировать - чесслово лениво:)

так и есть выполняет N раз
как решение
cross apply (select dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)) func(val)
28 мар 13, 16:56    [14108742]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Проверил:) Действительно, вычисляет N раз одно и то же... И кэширует в разные ExprNNNN... Жуть....
28 мар 13, 17:00    [14108770]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Мне кажется, здесь играет роль детерминированность функции.
28 мар 13, 17:04    [14108791]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
да ну
Guest
Cygapb-007
Проверил:) Действительно, вычисляет N раз одно и то же... И кэширует в разные ExprNNNN... Жуть....


как проверял

select
	sum(z), sum(z), sum(z), sum(z), sum(z)
from
(
	select 1 as val, 2 as z
	union all
	select 2 as val, 2 as z
	union all
	select 3 as val, 2 as z
	union all
	select 4 as val, 2 as z
) as d
group by val
having SUM(z) IN (1, 2, 5, 7, 8)


вроде 1 раз посчитанный sum(z) не вычисляется более.
28 мар 13, 17:19    [14108894]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
да ну
Guest
iap,

+15685
28 мар 13, 17:20    [14108896]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
да ну, при аггрегировании 1 раз вычисляется, не о нем речь
28 мар 13, 17:21    [14108904]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Получается, правильно будет объединять так:
FROM Table2 t2
cross apply(select getOutDialingPhoneNumber=dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime)) Calc1
JOIN Table1 t1 ON Calc1.getOutDialingPhoneNumber in (t1.SOT_CLIENT,...,t1.KT_3)
	AND ABS(DATEDIFF(MI, t1.date_modified + 0.25, t2.OfferedTime))<=30
28 мар 13, 17:27    [14108939]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
да ну
Guest
Cygapb-007,

да, не влияет даже детерменистик или не детерминистик. он вычисляет постоянно. профайлер показывает это.

гавно.
28 мар 13, 18:11    [14109195]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Rinatusss
Member

Откуда:
Сообщений: 6
Cygapb-007
лучше писать так:
ON (dbo.getOutDialingPhoneNumber(t2.Call_ID, t2.OfferedTime, t2.TerminatedTime) 
IN (t1.SOT_CLIENT, t1.SOT_CLIENT2, t1.SOT_CLIENT3, t1.DT_CLIENT, t1.RT_CLIENT, t1.DOP_NUM1, t1.DOP_NUM2, t1.KT_1, t1.KT_2, t1.KT_3))
Или функция по-любому будет вызвана 1 раз?

Вот я так уже сделал спасибо!
и на счет выборки последней записи, все таки какой метод лучше?
я использовал этот:
select login, status, date from mytable t1 where date=(select max(date) from mytable t2 where t2.login=t1.login)

но что то кажется он данные теряет.. будто не все выводятся
28 мар 13, 19:02    [14109437]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Rinatusss
Вот я так уже сделал спасибо!
Уже устарело, надо по-новому делать: 14108939 :))
28 мар 13, 19:05    [14109454]     Ответить | Цитировать Сообщить модератору
 Re: помогите с запросом пожалуйста  [new]
Rinatusss
Member

Откуда:
Сообщений: 6
Cygapb-007
Rinatusss
Вот я так уже сделал спасибо!
Уже устарело, надо по-новому делать: 14108939 :))


Реализовал предложенный вариант, время просчета запроса сократилось в 7 раз.. СУПЕР!
Спасибо большое за помощь!
29 мар 13, 13:48    [14112712]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить