Имя: Пароль:
1C
1С v8
Как получить записи из первой таблицы которых нет во второй?
,
0 Плот
 
23.08.13
09:08
Ребята привет!
Сабж.
Понимаю что как то нужно проверят на NULL, но только как?
1 shuhard
 
23.08.13
09:09
(0) есть NULL,
охеренная неожиданность ?
2 Sammo
 
23.08.13
09:09
Левое соединение и проверка на Есть NULL
3 Fragster
 
модератор
23.08.13
09:14
Где поле не в (выбрать поле из таблица2)
4 ДемонМаксвелла
 
23.08.13
09:15
5 Mouzem
 
23.08.13
09:20
а разве не ввели расстрел за NULL?
по мне, так только как говорит (3) делать, так и только так.
6 Лодырь
 
23.08.13
09:21
(3)(5) А теперь расскажите мне, что вы будете делать если в табличках более 1 поля.
7 Fragster
 
модератор
23.08.13
09:33
(6) Где (Поле1, Поле2) Не в (Выбрать Поле1, Поле2 Из Таблица2)
8 Fragster
 
модератор
23.08.13
09:34
(5) не, не ввели
9 dk
 
23.08.13
09:35
(6) соединение по нужному количеству полей
10 ДенисЧ
 
23.08.13
09:35
(5) Ввели расстрел за не использование естьнулла..
11 Креатив
 
23.08.13
09:39
(0)Можно ещё выбрать из первой таблицы записи, которых нет во внутреннем соединении.
12 Лодырь
 
23.08.13
09:50
(7) А чем выгоднее чем соединение?
13 timurhv
 
23.08.13
09:59
(7) Безбожно тормозит на больших объемах данных.
14 Fragster
 
модератор
23.08.13
10:34
(13) просто нужно понимать, как оно работает
15 acsent
 
23.08.13
10:35
(13) так это то же соединение, разве нет?
16 Fragster
 
модератор
23.08.13
11:11
переделал код из v8: Временные таблицы и индексы в запросах на "Не в" и Левое соединение ... есть NULL, запустил
17 Basilio
 
23.08.13
11:16
(10) А что не так с ЕстьNull-ом?
18 Fragster
 
модератор
23.08.13
11:22
(16)+
Количество ~160к, отбор ~8к, повторений: 1

Отбор через массив: 1
Отбор через левое соединение: 1
Отбор через не В: 189
Отбор через не В (Exists): 1
Отбор через внутреннее соединение + индекс: 1
Отбор через не В + индекс: 1
Отбор через не В (Exists) + индекс: 1
19 Fragster
 
модератор
23.08.13
11:28
дисквалифицировали В за унылость, увеличили повторения до 10:

Количество: 162 168 отбор: 8 108 повторений: 10
Отбор через массив: 18
Отбор через соединение: 16
Отбор через В (Exists): 17
Отбор через соединение + индекс: 16
Отбор через В + индекс: 17
Отбор через В (Exists) + индекс: 17
20 Dmitry77
 
23.08.13
11:28
можно загрузить обе таблицы в одну большую,добавить числовое поле, для первой 1, для второй 2.
Потом сгруппировать с сумированием по новому полю, потом отобрать только записи, где сумма = 1 (будут только те что в 1 таблице) =2 где только во второй = 3 где в обоих.
21 Dmitry77
 
23.08.13
11:50
(19) попробуй запусти через объединение, интересно сколько покажет времени.
22 Fragster
 
модератор
23.08.13
12:09
Количество: 162 170 отбор: 8 108 повторений: 10
Отбор через массив: 18
Отбор через соединение: 16
Отбор через В (Exists): 15
Отбор через соединение + индекс: 15
Отбор через В + индекс: 17
Отбор через В (Exists) + индекс: 16
Отбор через Объединение: 27
23 Fragster
 
модератор
23.08.13
12:09
Запрос.Текст =
"
|ВЫБРАТЬ
|    ТаблицаСсылок.Ссылка
|ПОМЕСТИТЬ ТаблицаСсылок
|ИЗ
|    &ТаблицаСсылок КАК ТаблицаСсылок
|
|ИНДЕКСИРОВАТЬ ПО
|    ТаблицаСсылок.Ссылка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|    Вложенный.Ссылка
|ИЗ
|    (ВЫБРАТЬ
|        Контрагенты.Ссылка КАК Ссылка,
|        1 КАК Группировка
|    ИЗ
|        Справочник.Контрагенты КАК Контрагенты
|    
|    ОБЪЕДИНИТЬ ВСЕ
|    
|    ВЫБРАТЬ
|        ТаблицаСсылок.Ссылка,
|        -1
|    ИЗ
|        ТаблицаСсылок КАК ТаблицаСсылок) КАК Вложенный
|
|СГРУППИРОВАТЬ ПО
|    Вложенный.Ссылка
|
|ИМЕЮЩИЕ
|    СУММА(Вложенный.Группировка) = 1";
24 Dmitry77
 
23.08.13
12:14
(22) спасибо.
25 Mouzem
 
23.08.13
12:14
Чет я не догнал, получается что объединить 2 таблицы и отобрать по нулу быстрее чем "не в"?
26 Fragster
 
модератор
23.08.13
13:00
(25) мораль в том, что нужно в каждом конкретном случае проверять отдельно разные варианты
27 viktor_vv
 
23.08.13
13:03
(16) Поэксприментировал немного с планами запросов.
Есть сомнение по корректности теста на exist. Конкретное на

|ГДЕ
|    (Контрагенты.Ссылка, ИСТИНА) В
|            (ВЫБРАТЬ
|                ТаблицаСсылок.Ссылка,
|                ИСТИНА
|            ИЗ
|                ТаблицаСсылок)

судя по тому во что 1С транслирует такую конструкцию для скуля ( из v8: Оператор "ИЛИ", конструкция "ВЫБОР" и вероятность фуллскана при них ) там получается  

AND EXISTS(SELECT
1
FROM #tt2 T2 WITH(NOLOCK)
WHERE (T1._Fld18873RRef = T2._Q_001_F_000RRef) AND (T1._Fld18875RRef = T2._Q_001_F_001RRef))

В случае если второе поле Истина, мне кажется, при трансляции его просто пропустят и останется exist по одному полю.

При этом для in и exist по одному полю строятся абсолютно одинаковые планы запроса.

Select
id
From sc72
Where id in (select id from #tempkl)

Select
id
From sc72 as sc
Where exists (select id from #tempkl where id = sc.id )

а вот для exsist по двум полям уже другой план c hash match

Select
id
From sc72 as sc
Where exists (select id from #tempkl where id = sc.id and sp81=sc.sp81)
28 Fragster
 
модератор
23.08.13
13:15
(27) за планы не смотрел, а факт в том, что В по одному полю транслируется в in, а по 2м и более - в exists (по крайней мере для mssql)
29 viktor_vv
 
23.08.13
13:20
(28) Согласен, но меня смущает именно второе поле Истина. Лучше бы может дернуть во временную таблицу реальное поле вместо Истина.

К тому же план для

Select
id
From sc72 as sc
Where exists (select id from #tempkl where id = sc.id and 1=1)

идентичен по одному полю и in.
30 Fragster
 
модератор
23.08.13
13:46
(29) да. а вот для НЕ В - уже очень разные планы, судя по времени выполнения, которое в 200 раз различается
31 viktor_vv
 
23.08.13
13:58
(30) Есть такое

Для in получается Nested loops / inner join

Для not in получается Merge join / Left anti semi join

это еще зависит от соотношения количества записей в таблицах и наличия индекса.
32 viktor_vv
 
23.08.13
14:00
(31)+ Для второго я не очень понимаю механизм этой операции, надо бы почитать умных книжек :).
Требовать и эффективности, и гибкости от одной и той же программы — все равно, что искать очаровательную и скромную жену... по-видимому, нам следует остановиться на чем-то одном из двух. Фредерик Брукс-младший