Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Горячая тема (более 10 ответов) Помогите оптимизировать запрос с суммами (число прочтений - 4953 )
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Помогите оптимизировать запрос с суммами
17. Января 2007 :: 15:51
Печать  
Есть вполне работающий и тупо написанный параметризированный запрос:

ТекстЗапроса="
|SELECT Type = CASE
|WHEN (SUM(Рег."+ИмяРесурсаОплатыСумма+")=0 AND (SUM(Рег."+ИмяРесурсаОплатыСуммаОплаты+")>0)) THEN 12
|WHEN (SUM(Рег."+ИмяРесурсаОплатыСумма+")>0 AND (SUM(Рег."+ИмяРесурсаОплатыСуммаОплаты+")>0)) THEN 9
|WHEN (SUM(Рег."+ИмяРесурсаОплатыСумма+")>0 AND (SUM(Рег."+ИмяРесурсаОплатыСуммаОплаты+")=0)) THEN 7
|ELSE 0
|END
|FROM
|"+ИмяТаблицыИтоговОплаты+" as Рег (nolock)
|WHERE
|Рег."+ИмяКредДокументОплаты+" = ?";

Имена ресурсов и реквизитов вынимаются по MetaDataWork, из самого запроса вытаскиваются числа для пиктограмм в колонках журнала.

У меня такое нехорошее подозрение, что здесь суммы вычисляются всякий раз и запрос требует оптимизации, т.е. один раз посчитать обе суммы, а затем уже их сравнивать, но всё в этом же одном запросе...

Но как? Помогите, плз...
  
Наверх
ICQ  
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #1 - 17. Января 2007 :: 17:32
Печать  
Неужели вложенным запросом?  Ужас
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #2 - 18. Января 2007 :: 07:35
Печать  
Ага, вложенным, наверное достаточно просто, только как правильно вложить и сравнить не соображу. Помогите плз ...
  
Наверх
ICQ  
IP записан
 
Quan
1c++ donor
1c++ power user
Отсутствует


I'm old, bald and ugly.

Сообщений: 273
Местоположение: Новосибирск -- Москва
Зарегистрирован: 20. Мая 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #3 - 18. Января 2007 :: 08:47
Печать  
Kapet писал(а) 18. Января 2007 :: 07:35:
Ага, вложенным, наверное достаточно просто, только как правильно вложить и сравнить не соображу. Помогите плз ...


Ну наверное так:

Select case when qq.s1>0 and qq.s2>0 Then ....... ELSE 0 END As Result
FROM
(
SELECT SUM(Поле1) As s1, SUM(Поле2) As s2
FROM
МояТаблица
WHERE
Поле3 = 'Условие'
) As qq
  

А для тех, кто не хотел учить SQL, господь сотворил курсоры
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #4 - 18. Января 2007 :: 10:32
Печать  
Парни, вы меня пугаете.  Ужас
С чего вы взяли, что суммы будут считаться несколько раз? Это же не 1С v8.0.
Stream Aggregate делается 1 раз, и уже готовый результат используется в Compute Scalar столько раз, сколько нужно. Зачем оптимизировать неоптимизируемое?  Озадачен (с)
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #5 - 18. Января 2007 :: 10:39
Печать  
Так ведь это..., я предполагал, что эти суммы нигде не кэшируются и вычисляются по новому каждый раз.

Хотя, так как в последнем запросе конечно красивее, да и наверное правильнее
  
Наверх
ICQ  
IP записан
 
DrACe
1c++ donor
1c++ power user
Отсутствует


1С++ любитель

Сообщений: 447
Местоположение: г. Новосибирск
Зарегистрирован: 23. Мая 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #6 - 18. Января 2007 :: 11:52
Печать  
мне все хотелось добавить умную мысль "надо бы посмотреть план выполнения...", но так как сам я этого делать практически не умею, то и сеять "разумное" вроде как не с руки  Озадачен
  
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #7 - 18. Января 2007 :: 12:00
Печать  
Почему имеет быть  Плачущий :

_RS=СоздатьОбъект("ODBCRecordset");
_RS.Отладка(фОтладка);
_RS.Подготовить(ТекстЗапроса);
_RS.ПостроитьПараметры();
_RS.УстПараметр(1,Конт.ТекущийДокумент);

SELECT CASE
WHEN QQ.S1=0 AND QQ.S2>0 THEN 12
WHEN QQ.S1>0 AND QQ.S2>0 THEN 9
WHEN QQ.S1>0 AND QQ.S2=0 THEN 7
ELSE 0
END As Result
FROM
(SELECT SUM(Рег.sp3526) as S1, SUM(Рег.sp3625) as S2
FROM RG3522 as Рег (nolock)
WHERE Рег.sp3525 = ?
) as QQ
Сообщить(_RS.ВыполнитьСкалярный());
{E:\DB1C\TORG_20070112\EXTFORMS\ОБРАБОТКИ\ПРОБА.ERT(16)}: State 07009, native 0, message [Microsoft][ODBC SQL Server Driver]Недопустимый индекс дескриптора

_RS.ПостроитьПараметры() возвращает 0
Работает ли типизация во вложенном запросе?
  
Наверх
ICQ  
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #8 - 19. Января 2007 :: 15:57
Печать  
И сам себе отвечаю: работает, если сделать так:

Если _RS.Подготовить(ТекстВложенногоЗапроса)=0 Тогда
     Сообщить("Не подготовили вложенный запрос!");
               Возврат;
КонецЕсли;
Если _RS.ПостроитьПараметры()=0 Тогда
     Сообщить("Не построили параметры вложенного запроса!");
     Возврат;
КонецЕсли;
Если _RS.Подготовить(ТекстЗапроса)=0 Тогда
     Сообщить("Не подготовили запрос!");
     Возврат;
КонецЕсли;
_RS.УстПараметр(1,Конт.ТекущийДокумент);
ТЗ=_RS.ВыполнитьИнструкцию();

ТекстВложенногоЗапроса="
     |SELECT SUM($Рег.Сумма) as S1, SUM($Рег.СуммаОплаты) as S2
     |FROM $РегистрИтоги.Оплаты as Рег (nolock)
     |WHERE $Рег.КредДокумент = ?";
ТекстЗапроса="
     |SELECT
     |      CASE
     |            WHEN QQ.S1=0 AND QQ.S2>0 THEN 12
     |            WHEN QQ.S1>0 AND QQ.S2>0 THEN 9
     |            WHEN QQ.S1>0 AND QQ.S2=0 THEN 7
     |      ELSE 0
     |      END As Result,
     |      CASE
     |            WHEN QQ.S1=0 AND QQ.S2>0 THEN 'Оплачен полностью'
     |            WHEN QQ.S1>0 AND QQ.S2>0 THEN 'Оплачено '+ CAST(QQ.S2 AS varchar(16))
     |            WHEN QQ.S1>0 AND QQ.S2=0 THEN 'Не оплачен'
     |      ELSE 'Списан в доход'
     |      END As OPLATA
     |FROM
     |("+ТекстВложенногоЗапроса+") as QQ";

Найдено методом тыка, и достаточно неочевидно, поэтому может в ФАК?

А можно ли оптимизировать последний "ТекстЗапроса"? А то как-то коряво получается, два раза сравниваю одно и тоже в CASE. А хочется одним разом вывести две разные колонки при одном проходе CASE...
  
Наверх
ICQ  
IP записан
 
Славко
Senior Member
****
Отсутствует



Сообщений: 467
Местоположение: Украина, г. Днепропетровск
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #9 - 19. Января 2007 :: 16:00
Печать  
Kapet писал(а) 18. Января 2007 :: 12:00:
Работает ли типизация во вложенном запросе?

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

Ламер, самый обычный ламер...    сначала мы ...   а потом мы ...
Наверх
wwwICQ  
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #10 - 19. Января 2007 :: 16:06
Печать  
Цитата:
Kapet писал(а) 18. Января 2007 :: 12:00:
Работает ли типизация во вложенном запросе?

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


Отвечаю. Данные запроса будут использоваться в журнале документа для колонок с пиктограммами и, заодно, для вывода строки состояния документа. Типизацию хочу для ускорения получения данных запроса, т.к. вроде, как везде написано, типизированный запрос компилируется один раз, а далее только успевай подставлять данные в переменные запроса.
Поправьте, если не прав. Если не прав, поправьте ФАК...
  
Наверх
ICQ  
IP записан
 
Quan
1c++ donor
1c++ power user
Отсутствует


I'm old, bald and ugly.

Сообщений: 273
Местоположение: Новосибирск -- Москва
Зарегистрирован: 20. Мая 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #11 - 20. Января 2007 :: 07:47
Печать  
Kapet писал(а) 19. Января 2007 :: 16:06:
Отвечаю. Данные запроса будут использоваться в журнале документа для колонок с пиктограммами и, заодно, для вывода строки состояния документа. Типизацию хочу для ускорения получения данных запроса, т.к. вроде, как везде написано, типизированный запрос компилируется один раз, а далее только успевай подставлять данные в переменные запроса.
Поправьте, если не прав. Если не прав, поправьте ФАК...


Поправляю. Только не ФАК, а тебя.
Один раз компилируется параметризированный запрос. Типизирован он или нет - рояли не играет.
А типизация - это приведение выдаваемых результатов к внутренним типам 1С, и во вложенных запросах она действительно нафиг не нужна.

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

Код
Выбрать все
	|set nocount on
	|
	|DECLARE @ТоварФильтр char(9)
	|
	|SET @ТоварФильтр = ?
	|
	|
	|DECLARE @ТекДата datetime
	|
	|SET @ТекДата = cast(? as datetime)
	|
	|
	|BEGIN TRANSACTION
	|
	|
	|
	|UPDATE $Справочник.Номенклатура with (updlock)
	|SET
	|$Справочник.Номенклатура.БазоваяЕдиницаИзмерения = seed.БазоваяЕдиницаИзмерения,
	|$Справочник.Номенклатура.ВалютаПродажи           = seed.ВалютаПродажи,
	|$Справочник.Номенклатура.ВалютаУчета             = seed.ВалютаУчета,
	|$Справочник.Номенклатура.ВидТовара               = seed.ВидТовара,
	|$Справочник.Номенклатура.ГруппаБест              = seed.ГруппаБест,            
	|$Справочник.Номенклатура.Категория               = seed.Категория,
	|$Справочник.Номенклатура.Плотность               = seed.Плотность,
	|$Справочник.Номенклатура.ТипТовара               = seed.ТипТовара,
	|$Справочник.Номенклатура.Субкатегория            = seed.Субкатегория,
	|$Справочник.Номенклатура.ГТД                     = seed.ГТД,
	|$Справочник.Номенклатура.Аналог                  = seed.Аналог,
	|$Справочник.Номенклатура.РазныеУпаковки          = seed.РазныеУпаковки,
	|$Справочник.Номенклатура.НормаУпаковки           = seed.НормаУпаковки,
	|$Справочник.Номенклатура.КолЕдВкор               = seed.КолЕдВкор,
	|$Справочник.Номенклатура.КоличествоВупаковке     = seed.КоличествоВупаковке
	|FROM
	|(
	|select
	|elements.ID as ИД,
	|m_list.$Справочник.Номенклатура.БазоваяЕдиницаИзмерения as БазоваяЕдиницаИзмерения,
	|m_list.$Справочник.Номенклатура.ВалютаПродажи           as ВалютаПродажи,
	|m_list.$Справочник.Номенклатура.ВалютаУчета             as ВалютаУчета,        
	|m_list.$Справочник.Номенклатура.ВидТовара               as ВидТовара,
	|m_list.$Справочник.Номенклатура.ГруппаБест              as ГруппаБест,
	|m_list.$Справочник.Номенклатура.Категория               as Категория,
	|m_list.$Справочник.Номенклатура.Плотность               as Плотность,
	|m_list.$Справочник.Номенклатура.ТипТовара               as ТипТовара,
	|m_list.$Справочник.Номенклатура.Субкатегория            as Субкатегория,
	|m_list.$Справочник.Номенклатура.ГТД                     as ГТД,
	|m_list.$Справочник.Номенклатура.Аналог                  as Аналог,
	|m_list.$Справочник.Номенклатура.РазныеУпаковки          as РазныеУпаковки,
	|m_list.$Справочник.Номенклатура.НормаУпаковки           as НормаУпаковки,
	|
	|CASE
	|WHEN colorz.$Справочник.Цвета.КолЕдВКор is NULL THEN m_list.$Справочник.Номенклатура.КолЕдВкор
	|WHEN colorz.$Справочник.Цвета.КолЕдВКор = 0 THEN m_list.$Справочник.Номенклатура.КолЕдВкор
	|ELSE colorz.$Справочник.Цвета.КолЕдВКор END
	|as КолЕдВкор,    
	|
	|CASE
	|WHEN m_list.$Справочник.Номенклатура.РазныеУпаковки=0 THEN m_list.$Справочник.Номенклатура.КоличествоВупаковке
	|ELSE elements.$Справочник.Номенклатура.КоличествоВупаковке
	|END
	|as КоличествоВупаковке
	|
	|FROM
	|(($Справочник.Номенклатура elements (NOLOCK)  
	|left join $Справочник.Номенклатура m_list (NOLOCK) on m_list.id=elements.$Справочник.Номенклатура.ГлавныйЛист)
	|left join $Справочник.Цвета colorz (NOLOCK) on colorz.id=elements.$Справочник.Номенклатура.Цвет)
	|where elements.$Справочник.Номенклатура.ГлавныйЛист = @ТоварФильтр
	|AND
	|elements.ID <> @ТоварФильтр
	|AND
	|elements.isfolder<>1
	|
	|) seed
	|
	|WHERE ID = SEED.ИД
	|
	|
	|
	|
	|DECLARE @vu TABLE ( objid CHAR(9), PRIMARY KEY CLUSTERED (objid) )
	|
	|INSERT INTO @vu
	|SELECT ID FROM
	|$Справочник.Номенклатура (NOLOCK)
	|WHERE
	|$Справочник.Номенклатура.ГлавныйЛист = @ТоварФильтр
	|AND
	|ID <> @ТоварФильтр
	|AND
	|isfolder<>1
	|
	|
	|
	|
	|exec _1sp__1SCONST_TLockX
	|
	|
	|
	|
	|delete from _1sconst
	|where
	|id in (select id from "+ИмяВрТаб+")
	|and
	|objid in (select * from @vu)
	|and docid = '     0   '
	|and date = @ТекДата
	|
	|
	|
	|
	|insert into _1sconst
	|(id, objid, date, value, docid, time, actno,lineno_,tvalue)
	|select seed.id as id, tlist.objid as objid, seed.date as date, seed.value as value, seed.docid as docid, seed.time as time, seed.actno as actno, seed.lineno_ as lineno_, seed.tvalue as tvalue
	|from
	|(select * from _1sconst
	|where
	|id in (select id from "+ИмяВрТаб+")
	|and
	|objid = @ТоварФильтр
	|and docid = '     0   '
	|and date = @ТекДата
	|) seed
	|cross join
	|@vu
	|tlist
	|
	|COMMIT TRANSACTION  

  

А для тех, кто не хотел учить SQL, господь сотворил курсоры
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите оптимизировать запрос с суммами
Ответ #12 - 21. Января 2007 :: 10:33
Печать  
Пардон, ошибочка вышла. Конечно речь шла не о "типизированном", а о параметризированном запросе...

Мда... Как говорится, чтобы задать вопрос нужно знать половину ответа. Этой половины я пока не знаю, а по сему маем что маем...

Спасибо людям, что хоть носом тыкают куда надо...
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать