Имя: Пароль:
1C
1С v8
Запрос на полное соответствие множеству
,
0 ComradeKite
 
03.10.17
18:49
Всем привет,
подскажите как запросом реализовать такое:

А(Т1,Т2)
Б(Т1,Т2,Т3)
С(Т1,Т3)

Задать список в условии (Т1,Т2) и получить в результате только А, при этом чтобы Б не попадало в запрос.
1 Филиал-msk
 
03.10.17
18:53
Описать условия задачи в терминах SQL - таблицах, колонках и строках. После этого решение будет лежать на поверхности.
2 ComradeKite
 
03.10.17
18:59
А, Б, С - Комплектация
Т1, Т2, Т3 - Номенклатура входящая в комплектацию

Может ссылка есть, где уже решалась задача?
Сходу у меня не получилось написать запрос, поэтому спрашиваю, может кто уже ковырял такую задачу?
3 Филиал-msk
 
03.10.17
19:11
Ну, если так, то вместо "Задать список в условии (Т1,Т2)" используй терминологию "Создать псевдокомплектацию Й(Т1,Т2)".
Тогда твоя задача сведется к "Найти среди А, Б, С, комплектацию, полностью совпадающую с Й"
4 ComradeKite
 
03.10.17
19:14
Ну так и есть)) Только вот как проверить в запросе что Й(Т1,Т2) = А(Т1,Т2)
5 Филиал-msk
 
03.10.17
19:20
(4) Описать условия задачи в терминах SQL (:

Й(Т1,Т2) = А(Т1,Т2) когда все строки из Й находятся в А и все строки из А находятся в Й.

Осталось понять, в каком виде доступны в запросе А, Б, С, Й, T1, T2, Т3
6 ComradeKite
 
03.10.17
19:36
Таблица "Комплекты"
Поле1 Комплектация(Тип Справочник "Комплектации")
Поле2 Номенклатура(Тип Справочник "Номенклатура")

Задаю предикат списком номенклатуры. Хочу получить на выходе комплектации, соответсвующие точному совпадению заданному списку.
7 Филиал-msk
 
03.10.17
19:41
(6) > Задаю предикат списком номенклатуры
Неверно. Если комплекты хранятся в таблице, то и "предикат" - таблица с полями.

Давай по частям. Представь, что у тебя уже есть в базе этот комплект Й и надо найти А, что строки Й совпадают с А.
Потом вынесешь описание Й в отдельную временную таблицу, и...
8 ComradeKite
 
03.10.17
19:50
Есть "В" в 1С, там список значений. Но если надо таблицу, то пусть будет таблица с одним полем "Номенклатура". В этой таблице находятся строки с номенклатурой, которая составляет комплект.

Во втором абзаце, я не совсем понимаю. Пусть там есть не один, а три Й(Т1,Т2), П(Т1,Т2), Р(Т1,Т2), я их циклом буде во временную таблицу перебирать? Если бы можно было, я бы вынес в отдельную таблицу и соединил бы с проверкой на нулл.
9 Филиал-msk
 
03.10.17
19:55
(8) Почти, почти, уже близко (;

1) Пусть у тебя в базе есть А(Т1,Т2), Б(Т1,Т2,Т3), С(Т1,Т3), Й(Т1, Т2). Ты можешь написать запрос, который скажет тебе, что А = Й (проверкой на null и.т.п)

2) Создаешь временную таблицу (одинаковую по структуре с остальными описаниями комплектов). Формируешь там описание Й по данным своего списка значений из 1С.

3) Модифицируешь запрос из п1, чтобы он сравнивал не таблицу с собой, а таблицу со времянкой из п2.
10 ComradeKite
 
03.10.17
20:03
Пытался понять, не понял))
11 Филиал-msk
 
03.10.17
20:15
(10) Пункт 1 можешь написать?
12 Филиал-msk
 
03.10.17
20:15
Выкладывай (:
13 ComradeKite
 
03.10.17
20:24
Ну сделал бы так

А, Т1
А, Т2
Й, Т1
Й, Т2

Выбрать Комплекты.Комплект, Комплекты1.Номенклатура ИЗ Комплекты
Полное Соединение ИЗ Комплекты КАК Комплекты1
ПО Комплекты.Номенклатура = Комплекты1.Номенклатура
ГДЕ
НЕ Комплекты.Комплект Есть Null ИЛИ
НЕ Комплекты1.Номенклатура Есть Null
14 mistеr
 
03.10.17
20:31
ВЫБРАТЬ
    Комплектация.Ссылка КАК Ссылка
ИЗ
    Документ.КомплектацияНоменклатуры.Комплектующие КАК Комплектация
        ЛЕВОЕ СОЕДИНЕНИЕ ВТОбразец КАК Образец
        ПО (Образец.Номенклатура = Комплектация.Номенклатура)
ГДЕ
    Комплектация.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО
    Комплектация.Ссылка

ИМЕЮЩИЕ
    КОЛИЧЕСТВО(Комплектация.Номенклатура) = КОЛИЧЕСТВО(Образец.Номенклатура) И
    КОЛИЧЕСТВО(Образец.Номенклатура) = &КоличествоОбразец
15 mistеr
 
03.10.17
20:32
(14) Предполагаем, что Номенклатура в ТЧ не повторяется.

КоличествоОбразец нужно посчитать заранее.
16 Филиал-msk
 
03.10.17
20:33
(13) Отлично. Только там в ГДЕ скорей всего И должно быть, а не ИЛИ

А теперь добавляем в начало
...
ПОМЕСТИТЬ
ОригинальныйКомплект
;

И исправляем
...
Полное Соединение ИЗ Комплекты КАК Комплекты1
на
ПОЛНОЕ СОЕДИЕНЕНИЕ ОригинальныйКомплект КАК Комплекты1

Идея понятна?
17 ComradeKite
 
03.10.17
20:38
mister, такая идея у меня была, но почему то отмел ее как не стабильный вариант решения. Надо сначала по количеству отсеять а потом все равно сверять. Но надо еще подумать. Это кстати код из типовой, поиск по образцу?

Филиал-msk, сейчас переварю информацию))
18 Филиал-msk
 
03.10.17
20:44
(14) Поменяй таблицы местами, будет еще проще
19 mistеr
 
03.10.17
20:51
(17) Нет, это из головы. Насчет стабильности не знаю, если номенклатура не повторяется, должно быть все OK. А вот по производительности точно выигрывает, полное соединение вещь тяжелая, в отличие от левого.

(18) По-моему, поменять местами нельзя, будет неверный результат. Тогда мы не отсеем Б из (0).
20 ComradeKite
 
03.10.17
20:51
Филиал-msk: твой вариант не получается отработать)) Буду сейчас пробовать с количеством.
21 Сти
 
03.10.17
22:36
(0) Ну есть пара вариантов.

Если (Т1,Т2) это список номенклатуры, входящей в комплектацию, и можно параметром передать количество элементов этого списка, то можно так:
ВЫБРАТЬ
    К1.А КАК А,
    К1.Т КАК Т
ПОМЕСТИТЬ К3
ИЗ
    Комплектация КАК К1
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ
            К0.А КАК А
        ИЗ
            Комплектация КАК К0
        ГДЕ
            НЕ К0.Т В (&НаборНоменклатуры)) КАК К2
        ПО К1.А = К2.А
ГДЕ
    К2.А ЕСТЬ NULL
;

/////////////////////
ВЫБРАТЬ
    К3.А
ИЗ
    К3 КАК К3

СГРУППИРОВАТЬ ПО
    К3.А

ИМЕЮЩИЕ
    КОЛИЧЕСТВО(К3.Т) = &Количество


Если же (Т1,Т2) не список, а таблица запроса, то
ВЫБРАТЬ
    К1.А КАК А,
    К1.Т КАК Т
ПОМЕСТИТЬ К3
ИЗ
    Комплектация КАК К1
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ
            К0.А КАК А
        ИЗ
            Комплектация КАК К0
        ГДЕ
            НЕ К0.Т В
                        (ВЫБРАТЬ
                            Комплектующие.Т
                        ИЗ
                            Комплектующие)) КАК К2
        ПО К1.А = К2.А
ГДЕ
    К2.А ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    К5.А
ИЗ
    К3 КАК К5
ГДЕ
    НЕ К5.А В
                (ВЫБРАТЬ
                    К4.А
                ИЗ
                    (ВЫБРАТЬ РАЗЛИЧНЫЕ
                        К3.А КАК А,
                        Комплектующие.Т КАК Т
                    ИЗ
                        К3 КАК К3,
                        Комплектующие КАК Комплектующие) КАК К4
                        ЛЕВОЕ СОЕДИНЕНИЕ К3 КАК К31
                        ПО
                            К4.А = К31.А
                                И К4.Т = К31.Т
                ГДЕ
                    К31.А ЕСТЬ NULL )


Первый вариант меньше нагрузит комп или сервер, так как во втором полностью пересекаются две таблицы, и если записей в них много, то будет понятно что.
22 ВРедная
 
03.10.17
23:01
А если привести все это добро к строкам?
Если это разовое действие, можно в цикле прогнать при обработке. Если регулярное - хранить вместе с данными.
Например, перечисление упорядоченных кодов через запятую? И сравнивать на равенство?
23 ComradeKite
 
04.10.17
17:53
Решил так:
1. Сначала сгруппировал по комплектации и посчитал количество номенклатуры в комплектации.
2. Сравнил количество с количеством номенклатурных позиций в отборе. Отсеял не совпадающие по количеству.
3. Соединил пункт 2 с 1 левым соединением. Там где Null отобрал в исключающую временную таблицу.
4. Взял 2 и отфильтровал 3.

Я такой вариант сразу придумал, но он мне показался не стабильным. Но после того как mister предложил такой вариант, я вернулся к нему и после фильтра записей по количеству, проверил еще на совпадение по номенклатуре.
Получилось очень стабильно.

Вот:

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура
ПОМЕСТИТЬ ВТ_Отбор1
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В(&Отбор1)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура
ПОМЕСТИТЬ ВТ_Отбор2
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В(&Отбор2)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СпецификацииНоменклатурыВыходныеИзделия.Ссылка КАК Ссылка,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СпецификацииНоменклатурыВыходныеИзделия.Номенклатура) КАК Количество
ПОМЕСТИТЬ ВТ_СпецификацияВсе1
ИЗ
    Справочник.СпецификацииНоменклатуры.ВыходныеИзделия КАК СпецификацииНоменклатурыВыходныеИзделия

СГРУППИРОВАТЬ ПО
    СпецификацииНоменклатурыВыходныеИзделия.Ссылка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СпецификацииНоменклатурыИсходныеКомплектующие.Ссылка КАК Ссылка,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СпецификацииНоменклатурыИсходныеКомплектующие.Номенклатура) КАК Количество
ПОМЕСТИТЬ ВТ_СпецификацияВсе2
ИЗ
    Справочник.СпецификацииНоменклатуры.ИсходныеКомплектующие КАК СпецификацииНоменклатурыИсходныеКомплектующие

СГРУППИРОВАТЬ ПО
    СпецификацииНоменклатурыИсходныеКомплектующие.Ссылка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Отбор1.Номенклатура) КАК Количество
ПОМЕСТИТЬ ВТ_Количество1
ИЗ
    ВТ_Отбор1 КАК ВТ_Отбор1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Отбор2.Номенклатура) КАК Количество
ПОМЕСТИТЬ ВТ_Количество2
ИЗ
    ВТ_Отбор2 КАК ВТ_Отбор2
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Спецификация.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_СпецификацииПоКоличеству1
ИЗ
    ВТ_СпецификацияВсе1 КАК ВТ_Спецификация,
    ВТ_Количество1 КАК ВТ_Количество
ГДЕ
    ВЫБОР
            КОГДА ВТ_Количество.Количество = ВТ_Спецификация.Количество
                ТОГДА ИСТИНА
            ИНАЧЕ ЛОЖЬ
        КОНЕЦ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_СпецификацияВсе2.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_СпецификацииПоКоличеству2
ИЗ
    ВТ_СпецификацияВсе2 КАК ВТ_СпецификацияВсе2,
    ВТ_Количество2 КАК ВТ_Количество2
ГДЕ
    ВЫБОР
            КОГДА ВТ_Количество2.Количество = ВТ_СпецификацияВсе2.Количество
                ТОГДА ИСТИНА
            ИНАЧЕ ЛОЖЬ
        КОНЕЦ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СпецификацииНоменклатурыВыходныеИзделия.Ссылка КАК Спецификации1
ПОМЕСТИТЬ ВТ_СпецификацииУбрать1
ИЗ
    Справочник.СпецификацииНоменклатуры.ВыходныеИзделия КАК СпецификацииНоменклатурыВыходныеИзделия
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Отбор1 КАК ВТ_Отбор1
        ПО (ВТ_Отбор1.Номенклатура = СпецификацииНоменклатурыВыходныеИзделия.Номенклатура)
ГДЕ
    СпецификацииНоменклатурыВыходныеИзделия.Ссылка В
            (ВЫБРАТЬ
                ВТ_СпецификацииПоКоличеству1.Ссылка
            ИЗ
                ВТ_СпецификацииПоКоличеству1)
    И ВТ_Отбор1.Номенклатура ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СпецификацииНоменклатурыИсходныеКомплектующие.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_СпецификацииУбрать2
ИЗ
    Справочник.СпецификацииНоменклатуры.ИсходныеКомплектующие КАК СпецификацииНоменклатурыИсходныеКомплектующие
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Отбор2 КАК ВТ_Отбор2
        ПО (ВТ_Отбор2.Номенклатура = СпецификацииНоменклатурыИсходныеКомплектующие.Номенклатура)
ГДЕ
    СпецификацииНоменклатурыИсходныеКомплектующие.Ссылка В
            (ВЫБРАТЬ
                ВТ_СпецификацииПоКоличеству2.Ссылка
            ИЗ
                ВТ_СпецификацииПоКоличеству2)
    И ВТ_Отбор2.Номенклатура ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_СпецификацииПоКоличеству1.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_ОтборРезультат1
ИЗ
    ВТ_СпецификацииПоКоличеству1 КАК ВТ_СпецификацииПоКоличеству1
ГДЕ
    НЕ ВТ_СпецификацииПоКоличеству1.Ссылка В
                (ВЫБРАТЬ
                    ВТ_СпецификацииУбрать1.Спецификации1 КАК Спецификации1
                ИЗ
                    ВТ_СпецификацииУбрать1 КАК ВТ_СпецификацииУбрать1)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_СпецификацииПоКоличеству2.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_ОтборРезультат2
ИЗ
    ВТ_СпецификацииПоКоличеству2 КАК ВТ_СпецификацииПоКоличеству2
ГДЕ
    НЕ ВТ_СпецификацииПоКоличеству2.Ссылка В
                (ВЫБРАТЬ
                    ВТ_СпецификацииУбрать2.Ссылка
                ИЗ
                    ВТ_СпецификацииУбрать2)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ОтборРезультат1.Ссылка КАК Результат
ИЗ
    ВТ_ОтборРезультат1 КАК ВТ_ОтборРезультат1
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ОтборРезультат2 КАК ВТ_ОтборРезультат2
        ПО ВТ_ОтборРезультат1.Ссылка = ВТ_ОтборРезультат2.Ссылка
24 Ildarovich
 
12.10.17
15:35
(23) Решение кажется неоправданно громоздким. Проще реализовать по аналогии с решением по ссылке: http://forum.infostart.ru/forum9/topic165116/message1728663/#message1728663.
Правда, там только один отбор (называется Эталон), но ничего не стоит добавить и второй - по выходным изделиям спецификации. Минимум нужно будет сравнивать не с двойкой, а с тройкой.
25 Сти
 
13.10.17
08:55
(24) тоже непонятно зачем так. (21) прекрасно работает, не знаю, зачем в итоге столько наворочено
Основная теорема систематики: Новые системы плодят новые проблемы.