Имя: Пароль:
1C
1C 7.7
v7: Проблема с запросом
,
0 pofigos
 
15.07.13
12:53
Всем добрый день. Работа остановилась, не могу понять как решить. Есть запрос:
ТекстЗапроса = "
       |SELECT
       |      РеализацияОбороты.Покупатель [Покупатель $Справочник.Контрагенты]
       |    , РеализацияОбороты.Товар [Товар $Справочник.ВидыТоваров]
       |    , РеализацияОбороты.ТипЦены [ТипЦены $Справочник.ТипыЦен]
       |    , РеализацияОбороты.Накладная [Накладная $Справочник.Документы]
       |    , Подзапрос.Филиал [Филиал $Справочник.Подразделение]
       |    , Подзапрос.Код
       |    , Подзапрос.Поставщик [Поставщик $Справочник.Контрагенты]
       |    , Sum(РеализацияОбороты.СуммаПриходнаяОборот) СуммаПриходная
       |    , Sum(РеализацияОбороты.СуммаОборот) СуммаСНДС
       |    , Sum(РеализацияОбороты.СуммаБезНДСОборот) СуммаБезНДС
       |    , Sum(РеализацияОбороты.КоличествоОборот) Количество
       |FROM $РегистрОбороты.Реализация(:НачДата,
       |        :КонДата~,,,"+Фильтр+",
       |        (Накладная, Покупатель, Товар, ТипЦены, Менеджер),) AS РеализацияОбороты
       |    INNER JOIN (SELECT Сотрудники.ID Ссылка
       |            , $Сотрудники.Филиал Филиал
       |            , ВидыТоваров.ID СсылкаТовар
       |            , ВидыТоваров.CODE Код
       |            , $ВидыТоваров.Поставщик Поставщик
       |            , Документы.ID СсылкаДокумент
       |            , $Документы.СсылкаНаДокумент СсылкаНаДокумент
       |        FROM $Справочник.ВидыТоваров AS ВидыТоваров
       |            CROSS JOIN $Справочник.Документы AS Документы
       |            CROSS JOIN $Справочник.Сотрудники AS Сотрудники "+ФильтрПодзапрос+") AS Подзапрос ON РеализацияОбороты.Менеджер = Подзапрос.Ссылка AND РеализацияОбороты.Товар = Подзапрос.СсылкаТовар AND РеализацияОбороты.Накладная = Подзапрос.СсылкаДокумент
       |GROUP BY РеализацияОбороты.Покупатель
       |    , РеализацияОбороты.Накладная
       |    , РеализацияОбороты.Товар
       |    , РеализацияОбороты.ТипЦены
       |    , Подзапрос.Филиал
       |    , Подзапрос.Код
       |    , Подзапрос.Поставщик
       |";

Думал к нему приклеить еще 1 подзапрос, который возвращал бы значение склада из документа. Проблема в том, что в регистре идет учет по филиалу. В подзапросе1 вытащил ссылку на документ. Каким образом выцепить склад? Записи делаются 3-мя документами. Пробовал через журнал.. то ли криво написано, то ли не верна мысль:

|    INNER JOIN (SELECT Журнал.IDDOC Документ
       |            , Журнал.IDDOCDEF Документ_вид,
       |        COALESCE($ДокТТН.МОЛ, $ДокАкт.МОЛ, $ДокВозвр.МОЛ) as  [Склад $Справочник.Склады]
       |        FROM _1SJourn as Журнал
       |            LEFT JOIN    $Документ.ТТННаОрганизациюТовары as ДокТТН ON ДокТТН.IDDoc = Журнал.IDDoc
       |            LEFT JOIN    $Документ.АктПриема as ДокАкт ON ДокАкт.IDDoc = Журнал.IDDoc
       |            LEFT JOIN    $Документ.ВозвратИзОрганизацииТоваров as ДокВозвр ON ДокВозвр.IDDoc = Журнал.IDDoc) as Подзапрос1 ON Подзапрос.СсылкаНаДокумент = Подзапрос1.Документ

Прошу подсказать и направить в нужное русло.
1 Ёпрст
 
15.07.13
13:13
CROSS JOIN $Справочник.Документы это сильно
2 pofigos
 
15.07.13
13:23
(1) Возможно. Выдал построитель данную конструкцию. Предложите варианты, если не сложно.
3 Ёпрст
 
15.07.13
13:25
Мне пока вообще не понять, зачем там такой подзапрос и что хранится в Справочник.документы
4 Ёпрст
 
15.07.13
13:25
и зачем делать 2 кросс джоина..
5 Ёпрст
 
15.07.13
13:25
и что в ФильтрПодзапрос еще не видно
6 Mikeware
 
15.07.13
13:29
прочитал. тоже работа остановилась...
7 pofigos
 
15.07.13
13:31
в справочнике документы хранятся ссылки на документы, как это не странно. Для чего это было сделано, уже не узнать, поэтому приходится поддерживать. Так же переделать регистр не получится, объем базы велик и документов много (10 лет базе, порядка 2000+ накладных в день). Если объяснить нагляднее:

Склад = Регситр.Накладная.СсылкаНаДокумент  , где Измерение Накладная типа справочник (вот так вот завели).
Поэтому при обращении к виртуальной таблице я не могу (в силу либо не знания, либо невозможности обратиться напрямую к документу, которые делал движение регистра)

Фильтры это условия по форме. Можно опустить данные вещи: к примеру:
Если ВыбТовар.ЭтоГруппа() = 1 Тогда
           ИмяТаблицы="#ГруппаТоваров";
           Запрос.УложитьСписокОбъектов(ВыбТовар,ИмяТаблицы,"ВидыТоваров");            
           Фильтр=Фильтр+"(Товар IN (SELECT Val FROM "+ИмяТаблицы+"))";    
       Иначе
           Фильтр = Фильтр+"(Товар = :ВыбТовар)";
           Запрос.УстановитьТекстовыйПараметр("ВыбТовар", ВыбТовар);            
       КонецЕсли;
8 pofigos
 
15.07.13
13:34
Подзапросом выбираю данные из Справочника Товаров(Поставщика/производителя как минимум), Из справичника Сотрудники (филиал менеджера), Из справочника Документы - ссылку на документ.

почему CROSS JOIN (Отсюда как бы можно посмтерть. Не думаю. что это критично:
...AS Подзапрос ON РеализацияОбороты.Менеджер = Подзапрос.Ссылка AND РеализацияОбороты.Товар = Подзапрос.СсылкаТовар AND РеализацияОбороты.Накладная = Подзапрос.СсылкаДокумент )
9 КонецЦикла
 
15.07.13
13:35
CROSS - это перемножение
Т.е. 10 документов * 10 элементов = 100
10 Ёпрст
 
15.07.13
13:39
Ну как тебе сказать, выкини на х..р подзапрос свой, он тебе не нужен совсем... вообще.

все условия устанавливай на параметры ВТ $РегистрОбороты.Реализация, наслаждайся.
11 pofigos
 
15.07.13
13:41
(9) не спорю с этим, и, считая, что данная конструкция уже устарела, перекинул на INNER. Меня больше интересует, как описать запрос к журналу документов и выдать 1 колонку "Cклад", зная что 3 вида документов участвует в выборке.

(10) Спасибо, согласен. Можно говорить прямо, критику расцениваю адекватно, тем более от грамотных людей.
12 Ёпрст
 
15.07.13
13:46
От запроса оставь только
$РегистрОбороты.Реализация

и присоедини 3 таблички шапки левым соединением к нему - получишь свой склад. усё.
13 pofigos
 
15.07.13
13:54
(12) Спасибо. буду пробовать
14 pofigos
 
15.07.13
15:06
(12) Спасибо за направление. плюсы в целом еще ен оценил, но все же понимаю, что так правильно делать.
Появился следующий вопрос. Текст запроса:
ТекстЗапроса = "
       |SELECT
       |      РеализацияОбороты.Покупатель [Покупатель $Справочник.Контрагенты]
       |    , РеализацияОбороты.Товар [Товар $Справочник.ВидыТоваров]
       |    , РеализацияОбороты.ТипЦены [ТипЦены $Справочник.ТипыЦен]
       |    , РеализацияОбороты.Накладная [Накладная $Справочник.Документы]
       |    , Sum(РеализацияОбороты.СуммаПриходнаяОборот) СуммаПриходная
       |    , Sum(РеализацияОбороты.СуммаОборот) СуммаСНДС
       |    , Sum(РеализацияОбороты.СуммаБезНДСОборот) СуммаБезНДС
       |    , Sum(РеализацияОбороты.КоличествоОборот) Количество
       |FROM $РегистрОбороты.Реализация(:НачДата
       |        ,:КонДата~,,
       |        RIGHT JOIN $Справочник.Сотрудники Сотрудники ON
       |            Сотрудники.ID=Менеджер AND $Сотрудники.Филиал = :ВыбФилиал,,
       |        (Накладная, Покупатель, Товар, ТипЦены, Менеджер),) AS РеализацияОбороты
       |GROUP BY РеализацияОбороты.Покупатель
       |    , РеализацияОбороты.Накладная
       |    , РеализацияОбороты.Товар
       |    , РеализацияОбороты.ТипЦены
       |";

Как получить в таблицу значение $Сотрудники.Филиал? (глупо, но все же)
15 Mikeware
 
15.07.13
15:11
(14) select :ВыбФилиал [Филиал $Справочник.Филиалы],
16 КонецЦикла
 
15.07.13
15:13
перед груп бай

LEFT JOIN $Справочник.Сотрудники AS Сотрудники ON РеализацияОбороты.Менеджер = ...

ну и добавить в селекте
17 Mikeware
 
15.07.13
15:14
(16) так у него выбран
18 Ёпрст
 
15.07.13
15:14
непонятно еще.. тебе точно там RIGHT JOIN нужен ?
19 Ёпрст
 
15.07.13
15:15
(16) это не надо, у него же фильтр на одно значение
20 КонецЦикла
 
15.07.13
15:22
Ладно, проехали :)
21 pofigos
 
15.07.13
15:56
(18) Да, проверено.
22 Ёпрст
 
15.07.13
16:08
(21) :)
ну как скажешь
23 Ёпрст
 
15.07.13
16:09
да, самое прикольное, что это соединение в этом тексте никак не используется, только выполнение запроса замедляет.
24 pofigos
 
15.07.13
16:30
(23) Интересно то, что при левом соединении он его вообще не учитывает. То есть выбирает все движения без учета фильтра. При правом выборка проходит корректно.
25 Ёпрст
 
15.07.13
16:31
(24) нам отсюда не видно ни одного фильтра
26 Ёпрст
 
15.07.13
16:33
в лучшем случае, твой right (в этом запросе) используется как inner join
27 Ёпрст
 
15.07.13
16:34
только ты еще кучу нуллов в итоге имеешь
28 pofigos
 
15.07.13
16:38
(26) Примерно так.
ТекстЗапроса = "
       |SELECT
       |      РеализацияОбороты.Покупатель [Покупатель $Справочник.Контрагенты]
       |    , РеализацияОбороты.Товар [Товар $Справочник.ВидыТоваров]
       |    , РеализацияОбороты.ТипЦены [ТипЦены $Справочник.ТипыЦен]
       |    , РеализацияОбороты.Накладная [Накладная $Справочник.Документы]
       |    , РеализацияОбороты.ФилиалСотр [Филиал $Справочник.Подразделение]
       |    , Sum(РеализацияОбороты.СуммаПриходнаяОборот) СуммаПриходная
       |    , Sum(РеализацияОбороты.СуммаОборот) СуммаСНДС
       |    , Sum(РеализацияОбороты.СуммаБезНДСОборот) СуммаБезНДС
       |    , Sum(РеализацияОбороты.КоличествоОборот) Количество
       |FROM $РегистрОбороты.Реализация(:НачДата
       |        ,:КонДата~,,
       |        RIGHT JOIN (SELECT Сотрудники.ID Ссылка
       |                    ,$Сотрудники.Филиал  ФилиалСотр
       |                    FROM $Справочник.Сотрудники AS Сотрудники) as Подзапрос ON    Подзапрос.Ссылка=Менеджер AND Подзапрос.ФилиалСотр = :ВыбФилиал
       |        ,(Товар IN (SELECT Val FROM ГруппаТоваров)),
       |        (Накладная, Покупатель, Товар, ТипЦены, Менеджер),) AS РеализацияОбороты

(27) На счет нуллов... По крайне мере в итоге не имею. Но на промежуточном этапе возможно да.
29 Ёпрст
 
15.07.13
16:40
right замени на inner
30 Ёпрст
 
15.07.13
16:40
иначе в выборке могут быть null поля везде.
31 Ёпрст
 
15.07.13
16:42
Хотя, выкини совсем это соединение и воткни условие на
Менеджер .
32 Ёпрст
 
15.07.13
16:46
|FROM $РегистрОбороты.Реализация(:НачДата
|        ,:КонДата~,,
|        ,(Товар IN (SELECT Val FROM ГруппаТоваров)) and (Менеджер in (SELECT Сотрудники.ID Ссылка from $Справочник.Сотрудники AS Сотрудники (nolock) where $Сотрудники.Филиал =:ВыбФилиал))
|        ,(Накладная, Покупатель, Товар, ТипЦены, Менеджер),) AS РеализацияОбороты
33 pofigos
 
15.07.13
17:12
(32) Спасибо,при выборе филиала выдает все обороты за период. Но мысль понятна.
34 Ёпрст
 
15.07.13
17:17
(33) а как должен ?
Ты же по филиалу только сотрудников/менеджеров отбираешь.
35 pofigos
 
15.07.13
17:37
Должен выдать те обороты, которые были по менеджерам (Список менеджеров формируется исходя от принадлежности к филиалу). По сути оставил в соединении:
SELECT Сотрудники.ID Ссылка
       |                    ,$Сотрудники.Филиал  ФилиалСотр
       |                    FROM $Справочник.Сотрудники AS Сотрудники) as Подзапрос ON    Подзапрос.Ссылка=Менеджер AND Подзапрос.ФилиалСотр = :ВыбФилиал

Такой вариант отрабатывает так как нужно.

Вопрос стоит другой, как мне в итоговую таблицу вытащить значение  Подзапрос.ФилиалСотр.
36 Ёпрст
 
15.07.13
17:55
(35) и  ?
1.
в моём запросе это так и есть, будут только те обороты, где менеджер принадлежит определенному филиалу.
2. см (15).
ЗЫ: нафига тебе это поле, когда оно и так всегда одно - ВыбФилиал.
37 pofigos
 
15.07.13
18:00
(36) Видимо некорректо высказался. Перед построение Теста запроса есть вот такое условие:
ФильтрПодзапрос = "";
   Если ПустоеЗначение(ВыбФилиал) = 0 Тогда
       ФильтрПодзапрос = "AND Подзапрос.ФилиалСотр = :ВыбФилиал";
       Запрос.УстановитьТекстовыйПараметр("ВыбФилиал", ВыбФилиал);
   КонецЕсли;

В зависимости от заполнения поля таблица или фильтруется по филиалу или нет (сделал так, т.к. других вариантов увы не знаю). Вопрос в том, если не будет заполнено поле, нужны обороты всех филиалов. Соответственно хотелось бы видеть их в итоговой таблице. Надеюсь понятно объяснил то, что хотел бы увидеть.

15 посмотрел, но не понял, куда записать.. в группировку или  куда еще( прошу объяснения для младенцев (((