понедельник, 2 февраля 2015 г.

1С++ - прямые запросы

Оригинал статьи на скрипт-кодинге: http://www.script-coding.com/Direct_queries.html
Копия статьи на скрипт-кодинге: http://ekorshunov.blogspot.com/2015/02/mssql-1-1.html

Статья на мисте: Эффективное использование MSSQL с помощью ВК 1C++

На форуме компоненты 1C++ есть Word'овая версия данной статьи, дополненная различиями в запросах к DBF и SQL базам:
Оригинал: http://www.1cpp.ru/forumfiles/Attachments/mod_002.zip
Копия: https://drive.google.com/file/d/0B5c2buazDySmanlpSTUzRHI4cDA/view?usp=sharing


Конструктор запросов для 1С++ (плагин для OpenConf): http://www.1cpp.ru/forum/YaBB.pl?num=1148127139
Ссылка на файл: http://www.1cpp.ru/forumfiles/Attachments/qryMaker.zip

Немного примеров http://www.1cpp.ru/forum:
+ пояснения к примерам из ветки http://www.1cpp.ru/forum/YaBB.pl?num=1148038411

Классический запрос, приводится в качестве примера. О конструкции ROLLUP - в конце текста.
ТекстЗапроса = "
|SELECT
|  Выборка.Склад as [Склад $Справочник.Склады]
|  СпрС.Descr as Склад_Наименование,
|  Выборка.Товар as [Товар $Справочник.Номенклатура],
|  СпрН.Descr as Товар_Наименование
|  Выборка.ИтогПоСкладам as ИтогПоСкладам,
|  Выборка.ИтогПоТоварам as ИтогПоТоварам,
|  Выборка.Количество as Количество
|FROM
|(
|SELECT
|  Рег.Склад as Склад,
|  Рег.Товар as Товар,
|  GROUPING(Рег.Склад) as ИтогПоСкладам,
|  GROUPING(Рег.Товар) as ИтогПоТоварам,
|  SUM(Рег.КоличествоОстаток) as Количество
|FROM
|  $РегистрОстатки.ОстаткиТоваров(:ВыбДата~,,
|                               Склад = :ВыбСклад AND Товар = @Товар,
|                               (Склад, Товар), (Количество)) as Рег
|GROUP BY
|  Рег.Склад, Рег.Товар WITH ROLLUP
|) as Выборка
|LEFT JOIN
|  $Справочник.Склады as СпрС ON СпрС.ID = Выборка.Склад
|LEFT JOIN
|  $Справочник.Номенклатура as СпрН ON СпрН.ID = Выборка.Товар
|ORDER BY
|  СпрС.Descr, СпрН.Descr, Выборка.ИтогПоСкладам DESC, Выборка.ИтогПоТоварам DESC
|";



ТекстЗапроса = "
| SELECT 
| Спр.Descr as Имя,
| Предст.Descr as ТорговыйПредставитель
|FROM
| $Справочник.Контрагенты as Спр (nolock)
| inner join $Справочник.Контрагенты as Предст (nolock) on Предст.id = $Спр.ТорговыйПредставитель
|WHERE
|left(Спр.CODE,2)='КЛ' 
|";
Пример выборки с условием:
CASE WHEN $ОпцииАвто.ЦенаПоАкции>0
THEN
 $ОпцииАвто.ЦенаПоАкции
ELSE
 $ОпцииАвто.Цена
END  



ТекстЗапроса = " 
|SELECT 
| Тов.Code as Код , 
| ТовРодитель.Code as КодРодитедь , 
| Рег.Товар as [Товар $Справочник.Товары], 
| Рег.КоличествоНачальныйОстаток as КоличествоНачОст, 
| Рег.КоличествоПриход as КоличествоПриход, 
| Рег.КоличествоРасход as КоличествоРасход, 
| Рег.КоличествоКонечныйОстаток as КоличествоКонОст 
|FROM 
| $РегистрОстаткиОбороты.ОстаткиТоваров(:НачДата, :КонДата~,,,, 
| Склад = :ВыбСклад, 
| (Товар), (Количество)) as Рег , 
| INNER JOIN 
| $Справочник.Товары as Тов ON 
| Тов.ID = Рег.Товар 
| LEFT JOIN 
| $Справочник.Товары as ТовРодитель ON 
| ТовРодитель.ID = Тов.ParentID 
|WHERE 
| Рег.Товар IN (SELECT Val FROM #Группа)";


С фильтром по группе товаров:
rc = СоздатьОбъект("ODBCRecordSet"); rc.УложитьСписокОбъектов(СписТоваров,"#Товары","Номенклатура"); ТекстЗапроса = "
 |select id [Товар $Справочник.Номенклатура] 
 |from $Справочник.Номенклатура
 |where ismark = 0
 |and (id IN (SELECT Val FROM #Товары))
 |order by descr";
ТЗ = rc.ВыполнитьИнструкцию(ТекстЗапроса);



Выборка документов разного вида:
SELECT
$ВидДокумента36.ПКО + ДокП.IDDoc [Док $Документ]
FROM $Документ.ПКО ДокП

UNION ALL

SELECT
$ВидДокумента36.РКО + ДокР.IDDoc [Док $Документ]
FROM $Документ.РКО ДокР
 
 
 
Получение остатков на ТА:
   ТекстЗапроса = "
   |Select
   |    Товар [Товар $Справочник.Товары],
   |    Склад [Склад $Справочник.Склады],
   |    ОстатокТовараОстаток ОстатокТовара
   |FROM
   |    $РегистрОстатки.ОстаткиТовара(
   | ,
   | ,
   | Товар in (Select val from #ВыбТовар)
   |       And
   | Склад in (Select val from #ВыбСклад),
   | (Товар, Склад),
   | ОстатокТовара
   | ) остатки
   |";
   Запрос = СоздатьОбъект("ODBCRecordSet");
   Запрос.УложитьСписокОбъектов(ВыбСклад,"#ВыбСклад","Склады");
   Запрос.УложитьСписокОбъектов(ВыбТовар,"#ВыбТовар","Товары");
   ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
   ТЗ.ВыбратьСтроку();
 
 
 
Группировка результата:
ТекстЗапроса="

|SELECT 
| $Регистр.ОстаткиТоваров.Товар as [Товар $Справочник.Номенклатура], 
| $Регистр.ОстаткиТоваров.Склад as [Склад $Справочник.МестаХранения], 
| SUM($Регистр.ОстаткиТоваров.ОстатокТовара) as Остаток, 
| GROUPING ($Регистр.ОстаткиТоваров.Товар) as Группа1, 
| GROUPING ($Регистр.ОстаткиТоваров.Склад) as Группа2 
|FROM $Регистр.ОстаткиТоваров 
|GROUP BY $Регистр.ОстаткиТоваров.Товар,$Регистр.ОстаткиТоваров.Склад WITH ROLLUP 
|ORDER BY $Регистр.ОстаткиТоваров.Товар,$Регистр.ОстаткиТоваров.Склад,Группа1 DESC,Группа2 DESC 
|"; На что стоит обратить внимание:
WITH ROLLUP это ключевое слово дает понять что надо добавлять пустые строки с итогами, что очень напоминает нам выгрузку в тз запроса 1С... но строки с итогами добавляются внизу, что нам неудобно.... поэтому добавим две колонки GROUPING... колонка эта ставит единицу если строчка добавлена ROLLUP и 0 если это просто строчка таблицы.... ну и в конце просто отсортируем по товарам, складам, и этим двум колонкам, и таким образом получим привычную нашему взгляду тз запроса 1С.





Пара ссылок, представляющих интерес в плане особенностей применения:

Расчет остатков на документ и по документ (пост №5 trad)
http://www.1cpp.ru/forum/YaBB.pl?num=1162733649/5#5

Текущие особенности и порядок деинициализации объектов ODBCRecordSet и ODBCDataBase
http://www.1cpp.ru/forum/YaBB.pl?num=1162472281/8#8 (пост №8 Quan)

Комментариев нет: