Имя: Пароль:
1C
1C 7.7
v7: 1C++ Прямой запрос помогите с решением.
0 AlexeyMK
 
26.05.12
12:35
Добрый день. Есть запрос:

"//{{ЗАПРОС(ПоДокументам)
|Период с  '01.01.1980' по ДатаКонца;
|
|Контрагент    = Регистр.Покупатели.Договор.Владелец,
|    Регистр.Поставщики.Договор.Владелец;
|
|КодОперации    = Регистр.Покупатели.КодОперации,
|    Регистр.Поставщики.КодОперации;
|
|ДолгВал        = Регистр.Покупатели.СуммаРуб,
|    Регистр.Поставщики.СуммаРуб;
|
|Группировка Контрагент без групп;
|
|Группировка Документ;
|
|Функция Расход = Приход(ДолгВал) Когда (КодОперации в СписокОперДебет);
|
|Функция Приход = Расход(ДолгВал) Когда (КодОперации в СписокОперКредит);
|
|Функция ИзначальнаяСумма = Расход(ДолгВал) Когда (КодОперации в СписокОперКредит);
|  
|"//}}ЗАПРОС
;

Помогите пожалуйста переложить его на прямой с помощью 1C++. Всю голову сломал уже.
2 МихаилМ
 
26.05.12
12:39
если б сломали, то привелибы код.
а так Вы просите написать за Вас
3 МастерВопросов
 
26.05.12
13:08
ну самое простое что приходит на ум:

Select
  <список полей через запятую>,
  <три CASE when <условие на КодОперации> и т.д.>
From <имя виртуальной таблицы оборотов Регистра "Покупатели">
Group by <Список полей группировки>
4 viktor_vv
 
26.05.12
14:36
(3) С виртуальной не получится. В виртуальной нету Реквизитов, а КодОперации это реквизит, по-моему. Во From Полное соединение реальных таблиц движений двух регистров, плюс левое соединение со справочником договора. Или Объединить Все для таблиц движений регистров, может быстрее будет.
5 МастерВопросов
 
26.05.12
16:19
(4) да да, ты прав. Еще я просмотрел что там два регистра Поставщики и Покупатели.
6 AlexeyMK
 
26.05.12
16:36
Я пытаюсь постепенно написать запрос. Вот что есть сейчас. Но поле Док почему то пустое:
Процедура ИнициализациSQL()
   ОлеДБ = СоздатьОбъект("OLEDBData");
   Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Mode=ReadWrite;Collating Sequence=MACHINE";
   Рез = ОлеДБ.Соединение(Соединение);
   ЗапросSQL = ОлеДБ.СоздатьКоманду();
   ЗапросSQL.Выполнить("EXECSCRIPT('SET ANSI OFF')");
   // Устанавливаем время ожидания захвата таблиц , если во время выполнения запроса кто то проводит документы
   // Очень полезная функция - аналогична времени ожидания в 1С
   ЗапросSQL.Выполнить("EXECSCRIPT('SET REPROCESS TO 60 SECONDS')");
   // Убираем буфепизацию, чтобы данные возвращаемые запросам всегда были актуальны
   ЗапросSQL.Выполнить("EXECSCRIPT('SET REFRESH TO 0,-1')");
   ЗапросSQL.Выполнить("Exec('SET TABLEVALIDATE TO 0')");// Отключили блокировки
КонецПроцедуры

...

ИнициализациSQL()


ТекстЗапроса = "
|SELECT
|    tmp.Контрагент as [Контрагент $Справочник.Контрагенты]
|    ,tmp.Док AS [Документ $Документ]
|    ,SUM(tmp.СуммаРуб) AS Приход
|    ,SUM(tmp.СуммаРуб1) AS Расход
|
|FROM (
|
|    SELECT
|        Дог1.parentext AS Контрагент
|        ,Рег.IDDoc as Док
|        ,Жур.IDDocDef as Док_вид  
|        ,$Рег.СуммаРуб AS СуммаРуб
|        ,$Рег.СуммаРуб AS СуммаРуб1
|    FROM
|        $Регистр.Покупатели AS Рег
|
|    LEFT JOIN $Справочник.Договоры as Дог1 on Дог1.id = $Рег.Договор
|
|    INNER JOIN 1sjourn AS Жур ON Жур.Iddoc = Рег.IDDoc AND
|        DTOS(Жур .date)+Жур .time+Жур .iddoc BETWEEN
|      DTOS(:НачДата~~)+'      '+'         '
|      And DTOS(:КонДата~~)+'ZZZZZZ'+'ZZZZZZZZZ'
|
|    UNION ALL
|
|    SELECT
|        Дог2.parentext AS Контрагент
|        ,Рег1.IDDoc as Док
|        ,Жур.IDDocDef as Док_вид  
|        ,$Рег1.СуммаРуб AS СуммаРуб
|        ,$Рег1.СуммаРуб AS СуммаРуб1
|    FROM
|        $Регистр.Поставщики AS Рег1
|
|    LEFT JOIN $Справочник.Договоры as Дог2 on Дог2.id = $Рег1.Договор
|
|    INNER JOIN 1sjourn AS Жур ON Жур.Iddoc = Рег1.IDDoc AND
|        DTOS(Жур .date)+Жур .time+Жур .iddoc BETWEEN
|      DTOS(:НачДата~~)+'      '+'         '
|      And DTOS(:КонДата~~)+'ZZZZZZ'+'ZZZZZZZZZ') as tmp
|
|
|GROUP BY tmp.Контрагент,tmp.Док
|";

ЗапросSQL.УстановитьТекстовыйПараметр("НачДата", Дата('01.01.1980'));
ЗапросSQL.УстановитьТекстовыйПараметр("КонДата", ДатаКонца);
ТЗ = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);
ТЗ.ВыбратьСтроку();
7 МастерВопросов
 
26.05.12
17:01
не уверен, но попробуй так "INNER JOIN 1sjourn AS Жур ON Жур.Iddoc = substring(Рег1.IDDoc,5,9)"
8 МастерВопросов
 
26.05.12
17:04
(6) и у тебе не совсем верно запрос составлен

либо выноси условие "DTOS(Жур .date)+Жур .time+Жур .iddoc BETWEEN
|       DTOS(:НачДата~~)+'      '+'         '
|       And DTOS(:КонДата~~)" в "where"
либо "LEFT JOIN $Справочник.Договоры" замени на "INNER JOIN"
9 leshikkam
 
26.05.12
17:05
А не проще класс ПрямойЗапрос использовать с 1sqlite - там удобней писать.
10 МастерВопросов
 
26.05.12
17:15
(8) нет, блин, в (6) всё верно.  Извини.
Так у тебя, вообще, запрос записей не возвращает, или только поле "Документ" пустое?
11 AlexeyMK
 
26.05.12
17:18
>МастерВопросов
Запрос возвращает записи, но поле Док пусто, идут только контрагенты. причем если я убираю JOIN со справочником Договоры, все нормально.
12 МастерВопросов
 
26.05.12
17:19
13 МастерВопросов
 
26.05.12
17:24
(11) ну в порядке бреда попробуй убрать типизацию [Документ $Документ] и так посмотри будут ссылки в этом поле?
14 AlexeyMK
 
26.05.12
17:27
>МастерВопросов(13)
Щас проверю
15 AlexeyMK
 
26.05.12
17:44
Хм... Вот так вот этот этап похоже "взлетел":

ТекстЗапроса = "

|
|    SELECT
|        Дог1.parentext AS [Контрагент $Справочник.Контрагенты]
|        ,Рег.IDDoc as [Док $Документ]
|        ,Жур.IDDocDef as Док_вид  
|        ,$Рег.СуммаРуб AS СуммаРуб
|        ,$Рег.СуммаРуб AS СуммаРуб1
|    FROM
|        $Регистр.Покупатели AS Рег
|
|    LEFT JOIN $Справочник.Договоры as Дог1 on Дог1.id = $Рег.Договор
|
|    INNER JOIN 1sjourn AS Жур ON Жур.Iddoc = Рег.IDDoc AND
|        DTOS(Жур .date)+Жур .time+Жур .iddoc BETWEEN
|      DTOS(:НачДата~~)+'      '+'         '
|      And DTOS(:КонДата~~)+'ZZZZZZ'+'ZZZZZZZZZ'
|
|    UNION ALL
|
|    SELECT
|        Дог2.parentext AS [Контрагент $Справочник.Контрагенты]
|        ,Рег1.IDDoc as [Док $Документ]
|        ,Жур.IDDocDef as Док_вид  
|        ,$Рег1.СуммаРуб AS СуммаРуб
|        ,$Рег1.СуммаРуб AS СуммаРуб1
|    FROM
|        $Регистр.Поставщики AS Рег1
|
|    LEFT JOIN $Справочник.Договоры as Дог2 on Дог2.id = $Рег1.Договор
|
|    INNER JOIN 1sjourn AS Жур ON Жур.Iddoc = Рег1.IDDoc AND
|        DTOS(Жур .date)+Жур .time+Жур .iddoc BETWEEN
|      DTOS(:НачДата~~)+'      '+'         '
|      And DTOS(:КонДата~~)+'ZZZZZZ'+'ZZZZZZZZZ'
|
|";

Тогда следующий вопрос, если уже помощь близко:

Вот эта конструкция как ты сказал, может реализоваться с помощью CASE-ов:

|Функция Расход = Приход(ДолгВал) Когда (КодОперации в СписокОперДебет);
|Функция Приход = Расход(ДолгВал) Когда (КодОперации в СписокОперКредит);


Т.е правильно я понимаю, что вот как нибудь так:

|    SELECT
|        Дог1.parentext AS [Контрагент $Справочник.Контрагенты]
|        ,Рег.IDDoc as [Док $Документ]
|        ,Жур.IDDocDef as Док_вид  
|        ,(CASE WHEN Рег.КодОперации IN(стрУсловиеДебет) THEN Рег.СуммаРуб AS Приход)
|               ,(CASE WHEN Рег.КодОперации IN(стрУсловиеКредит) THEN Рег.СуммаРуб AS Расход)

Или как нибудь по другому? Не пойму. В обычном запросе, список операций дебет и список операций кредит разные, соответственно у меня в разные суммы попадают расходы и приходы. А здесь как?
16 viktor_vv
 
26.05.12
17:49
У таблицы дивжений регистра остатков есть поле debkred, признак вида движения (приход расход). Кажись 0 это приход, 1 это расход.
17 viktor_vv
 
26.05.12
17:52
И ты бы таки под ДБФ sqlite использовал, там поудобнее будет и УложитьСписокОбъектов() работать будет для условий. А то тут еще и проблемы будут при монопольном доступе.
18 AlexeyMK
 
26.05.12
17:57
>viktor_vv
Сейчас попробую про sqlite почитать. Насколько я понял это внешняя библиотека, сам движок с DBF не надо на SQL переводить?
19 viktor_vv
 
26.05.12
18:02
(18) Не, переводить никуда ненадо. А для получения суммы что такое надо будет.

Sum($РегОст.чСумма * (1 - РегОст.debkred)) as СуммаПриход

Sum($РегОст.чСумма * РегОст.debkred) as СуммаРасход
20 viktor_vv
 
26.05.12
18:07
Вот тут смотри http://snegopat.ru/1sqlite/index .
21 AlexeyMK
 
26.05.12
18:18
(20) Спасибо.
22 AlexeyMK
 
26.05.12
19:34
Просьба ответить на еще несколько вопросов:

В запросе есть обращение к реквизиту документа -

|Торговый     = Регистр.Покупатели.ТекущийДокумент.Торговый,
|    Регистр.Поставщики.ТекущийДокумент.Торговый;

в SQL обращение к документу происходит через IDDoc и IDDocDef. Как добраться до реквизита документа?

И еще ответ на предыдущий вопрос, как правильно выбрать приходы и расходы по КодуОпераций?
23 viktor_vv
 
26.05.12
19:44
Судя по тексту Торговый это общий реквизи ?
24 AlexeyMK
 
26.05.12
19:50
(23) да, это общий реквизит документа.
25 SnarkHunter
 
26.05.12
20:02
(24)Общий реквизит документ с отбором или нет?
26 AlexeyMK
 
26.05.12
20:08
(25) да с отбором.
27 SnarkHunter
 
26.05.12
20:10
Тогда это _1sjourn.$ОбщийРеквизит.Торговый
28 AlexeyMK
 
26.05.12
20:26
(27) Точно!
29 ЧеловекДуши
 
28.05.12
13:05
>>> 01.01.1980
Не продуктивный запрос, через пару лет отомрет даже на SQL версии :)
...Что за отчет хоть делаешь, что нужна расшифровка по документно?
30 Ёпрст
 
гуру
28.05.12
13:42
(15) в дбф свой "case", там немного другой синтаксис + icase это

(22) воткнуть условие на код в расчет функции sum вестимо
31 AlexeyMK
 
28.05.12
20:56
(29) Нарушен партионный учет, попытка формирования отчета по ПДЗ.
(30) Да, спасибо я уже понял. Использовал ICASE(INLIST(val,1,2,3),true,false)
Программист всегда исправляет последнюю ошибку.