Имя: Пароль:
1C
1С v8
задачка оптимальный запрос
0 andryscha1c
 
09.10.21
21:08
Есть Таблица1
Иванов
Петров
Сидоров
Бикмамбетов

Таблица2
Иванов
Петров

Можно ли получить только те записи из первой таблицы, которых нет во второй? то есть Сидоров, Бикмамбетов, использую запрос и ТОЛЬКО закладку связи соеденения без закладки условия? и как на ваш взгляд оптимальнее было бы построить запрос?
1 pechkin
 
09.10.21
21:13
Не в (...)
2 andryscha1c
 
09.10.21
21:25
(1) это же условие получается, сейчас речь только про связи, можно ли на том уровне отсечь записи
3 Asmody
 
09.10.21
21:26
что оптимальнее - тебе расскажет только профайлер
4 Asmody
 
09.10.21
21:27
(2) отсечь записи, которых нет? да вы, батенька, затейник
5 andryscha1c
 
09.10.21
21:29
(4) отсечь записи с первой таблицы, как же нет то сынок
6 RomanYS
 
09.10.21
21:30
(2) левое соединение и условие есть null на вторую таблицу. Без условий совсем не получится
7 andryscha1c
 
09.10.21
21:33
(6) ну да, так и сделал. если совсем ни как без условий то вопросов нет.
это же оптимальнее будет если не использовать связи, а все сделать на уровне условий c Не в (...)?
8 exwill
 
09.10.21
21:51
(0) В любом случае решается задача "найти все соответствия таблицы1 и таблицы2". Она может решаться быстрее или медленнее в зависимости от того есть ли подходящие индексы или их нет. Но это всегда "под капотом". Повлиять на это можно только путем создания индексов, если их нет. В вашем случае они, как видно, есть. Поэтому выбросьте из головы. Пустое это
9 pechkin
 
09.10.21
21:54
(7) в некоторых случаях не работает быстрее чем соединение
10 exwill
 
09.10.21
21:55
Если делать нечего. Можете попробовать объединить и сгруппировать. Результат тот же. Но вряд ли быстрее
11 серый КТУЛХУ
 
09.10.21
21:59
ВЫБРАТЬ "Иванов" КАК Фио ПОМЕСТИТЬ втФио1
ОБЪЕДИНИТЬ ВЫБРАТЬ "Петров"
ОБЪЕДИНИТЬ ВЫБРАТЬ "Сидоров"
ОБЪЕДИНИТЬ ВЫБРАТЬ "Бекмамбетов"
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ "Иванов" КАК Фио ПОМЕСТИТЬ втФио2
ОБЪЕДИНИТЬ ВЫБРАТЬ "Петров"
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ втФио1.Фио, ВЫБОР КОГДА втФио2.Фио ЕСТЬ NULL ТОГДА 1 ИНАЧЕ 0 КОНЕЦ КАК ПрФио2
ПОМЕСТИТЬ ФиоПр
ИЗ втФио1 КАК втФио1 ЛЕВОЕ СОЕДИНЕНИЕ втФио2 КАК втФио2 ПО втФио1.Фио = втФио2.Фио
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ФиоПр.Фио
ИЗ
    ФиоПр КАК ФиоПр
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ФиоПр КАК ФиоПр1
        ПО (ФиоПр.Фио = ФиоПр1.Фио
                И ФиоПр1.ПрФио2 = 1)
12 серый КТУЛХУ
 
09.10.21
22:18
//или совсем короче
ВЫБРАТЬ "Иванов" КАК Фио ПОМЕСТИТЬ Фио1 ОБЪЕДИНИТЬ ВЫБРАТЬ "Петров"
ОБЪЕДИНИТЬ ВЫБРАТЬ "Сидоров" ОБЪЕДИНИТЬ ВЫБРАТЬ "Бекмамбетов" ;
ВЫБРАТЬ "Иванов" КАК Фио ПОМЕСТИТЬ Фио2 ОБЪЕДИНИТЬ ВЫБРАТЬ "Петров" ;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ Фио1.Фио КАК Фио, Фио2.Фио ЕСТЬ NULL КАК ПрФио ПОМЕСТИТЬ втФио
ИЗ Фио1 ЛЕВОЕ СОЕДИНЕНИЕ Фио2 ПО Фио1.Фио = Фио2.Фио ;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ втФио1.Фио, втФио2.Фио ЕСТЬ NULL КАК ПрФио
ИЗ втФио КАК втФио1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ втФио КАК втФио2 ПО (втФио1.Фио = втФио2.Фио И втФио1.ПрФио)
13 Ненавижу 1С
 
гуру
09.10.21
22:21
(11) ну да.
С таким же успехом я могу создавать временную таблицу с единственной записью единственного поля (это неважно) и делать внутреннее соединение исходных данных с этой таблицей. При этом всю секцию Где загонять условие связи.
Профит: без условий в секции где
14 Garykom
 
гуру
09.10.21
22:23
(0) если ты хочешь https://oracleplsql.ru/except-sql.html

то в 1С стандартно
https://its.1c.ru/db/metod8dev/content/2499/hdoc
15 acht
 
09.10.21
22:25
(12) Все проще

ВЫБРАТЬ
    Таблица1.ФИО
ИЗ
    Таблица1
ЛЕВОЕ СОЕДИНЕНИЕ
    Таблица2
ПО    
    Таблица1.ФИО = Таблица2.ФИО
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
(
    ВЫБРАТЬ 1
) КАК Фильтр
ПО
    Таблица2.ФИО ЕСТЬ NULL
16 acht
 
09.10.21
22:28
(13) Ну да, оно и есть
17 Garykom
 
гуру
09.10.21
22:30
итого я насчитал 3 способа
интересно какой шустрей
18 acht
 
09.10.21
22:31
(17) > какой шустрей
Зависит от исходных данных, как всегда
19 серый КТУЛХУ
 
09.10.21
22:52
(15): (короче - но не проще) спасибо! не знал такого приема...
20 GANR
 
10.10.21
00:18
(0) а чего глядеть то? генерируешь данные по миллиону строк, открываешь профайлер и пробуешь
21 pechkin
 
10.10.21
14:25
давеча была задача:
Найти все элементы справочника, что не встречаются в регистре (блоками по 10000 штук)
Сначала сделал все через соединение и ЕСТЬ NULL. Тормозило. Потом переделал на НЕ В (...) залетало
22 серый КТУЛХУ
 
10.10.21
14:33
(21): попал в индекс?..
23 acht
 
10.10.21
15:59
(22) Операцией "НЕ" ? =)
24 Dmitry77
 
10.10.21
16:10
Обеденить
Таблица.Фио
1 как колво

Обеденить
Таблица2. Фио
1

В вт1

Вт1.фио
Сумма(вт1.колво)
В вт2
Группировка вт1.фио

Выбрать различные
1 как контроль
В вт3

Вт2.фио
Внутренне соединение вт2.количество = вт3.контроль

Как то так без условий.
25 acht
 
10.10.21
16:32
(24) Надо доработать:

ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1 ИСТИНА КАК Контроль
В вт3

И потом
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
...
ПО
    вт3.контроль = вт2.количество = 1
26 NurSagen
 
10.10.21
19:24
1 таблица
   Внутреннее с 1 же таблицей
    , Которая "лево" соединена со второй где фамилии не равны
27 Said_We
 
15.10.21
14:45
(0) Как мне кажется, то на 1С оптимальнее вообще без соединения, но с условием.
Если не на 1С, то в SQL есть разность множеств - EXCEPT и соответственно есть NOT EXCEPT.
28 Said_We
 
15.10.21
14:52
"NOT EXCEPT" - только это прям так не пишется :-)
Ща прочитал и сам понял, что могу быть не понят.
29 Жан Пердежон
 
15.10.21
14:55
У скуля даже спец.физическая операция для твоей задачи есть: Left Anti Semi Join
Как это в запросе реализовать из названия должно быть ясно.
30 Kassern
 
15.10.21
15:19
какой то такой изврат получился))
    Запрос=Новый Запрос;
    Запрос.Текст="ВЫБРАТЬ
                 |    ТЗ1.Имя КАК Имя
                 |ПОМЕСТИТЬ ТЗ1
                 |ИЗ
                 |    &ТЗ1 КАК ТЗ1
                 |;
                 |
                 |////////////////////////////////////////////////////////////////////////////////
                 |ВЫБРАТЬ
                 |    ТЗ2.Имя КАК Имя
                 |ПОМЕСТИТЬ ТЗ2
                 |ИЗ
                 |    &ТЗ2 КАК ТЗ2
                 |;
                 |
                 |////////////////////////////////////////////////////////////////////////////////
                 |ВЫБРАТЬ
                 |    ТЗ1.Имя КАК Имя
                 |ИЗ
                 |    ТЗ1 КАК ТЗ1
                 |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТЗ2 КАК ТЗ2
                 |        ПО (НЕ ТЗ1.Имя В
                 |                    (ВЫБРАТЬ
                 |                        ТЗ2.Имя
                 |                    ИЗ
                 |                        ТЗ2))
                 |
                 |СГРУППИРОВАТЬ ПО
                 |    ТЗ1.Имя";
31 Said_We
 
15.10.21
15:25
(0) Без закладки условие - это на собеседовании такие вещи спрашивают что ли? :-)
Выкопайте яму руками, хотя лопата тут есть и стоит, но пользоваться ей нельзя. Но можно палкой копалкой в виде условия в JOIN.
Т.е. условие в JOIN использовать можно, а в Where нельзя? :-)

А придумать другое тестовое задание по интереснее можно? ....
32 Kassern
 
15.10.21
15:28
(30) потестил на 10тыс записях (в каждой таблице) в сравнении с обычным:
|ГДЕ ЕСТЬNULL(ТЗ2.Имя, """") = """"";
Быстрее отрабатывает с условием Где чем в связях.
33 серый КТУЛХУ
 
15.10.21
15:33
(30): см.(15), "все уже украли до нас" (с)
|ВЫБРАТЬ ТЗ1.Имя КАК Имя
|ИЗ ТЗ1 КАК ТЗ1
|   ЛЕВОЕ СОЕДИНЕНИЕ ТЗ2 КАК ТЗ2 ПО ТЗ1.Имя = ТЗ2.Имя
|   ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ 1) КАК Фильтр ПО ТЗ2.Имя ЕСТЬ NULL
34 Kassern
 
15.10.21
15:34
(33) не удивлен) прост лень было всю ветку читать
35 Kassern
 
15.10.21
15:42
Может кто объяснить, в каком случае такой подход через соединения выгоден по сравнению с обычным условием отсекающим в ГДЕ?
36 eTmy
 
15.10.21
15:46
(35) только когда надо потешить самооценку, что смог без блока где ¯\_(ツ)_/¯
37 Said_We
 
16.10.21
02:34
(35) Внутреннее левое соединение с небольшой таблицей и с правильными индексами. Выгоден просто визуально читать кому-то. Как правило, по скорости будет примерно тоже самое, а читать некоторым удобнее через внутреннее соединение - как фильтр читают.
JOIN - убийца производительности. Если можно без JOIN решить задачу, то надо решать без JOIN.
38 xXeNoNx
 
16.10.21
02:37
(0) покажи свое решение
39 rphosts
 
16.10.21
04:53
(15) очень напоминает нутро РЛС
Программист всегда исправляет последнюю ошибку.