Модераторы: Akella

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Несовпадающие записи, Выбор записей из табл которых нет 2 табл 
:(
    Опции темы
Zipper
Дата 27.4.2007, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



Есть таблица A и таблица Б. Структура таблиц одинаковая.
Надо выбрать из таблицы Б записи которых нет в таблице А.
Операций MINUS у нас нет?

Это сообщение отредактировал(а) Zipper - 27.4.2007, 11:40
PM MAIL   Вверх
Akella
Дата 27.4.2007, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



http://forum.vingrad.ru/forum/topic-146682.html

Это сообщение отредактировал(а) Akella - 28.4.2007, 15:52
PM MAIL   Вверх
chief39
Дата 27.4.2007, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


карманная тигра
***


Профиль
Группа: Участник Клуба
Сообщений: 1631
Регистрация: 20.5.2005
Где: Киев

Репутация: нет
Всего: 77



Код

select * 
from A
where A.id not in(
                             select id
                             from B
                           )



--------------------
Люди - это свечи. Они либо горят, либо их - в жопу!(с)

PM MAIL   Вверх
Zipper
Дата 28.4.2007, 05:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



Цитата

Код

select * 
from A
where A.id not in(
                             select id
                             from B         )


А при использовании такого запроса на большой базе (2 млн. записей), у меня он не работал. Как только ограничивал выборку до 200-500 тыс. записей все ок! В FireBird (версия 1.5.3) есть какието ограничения на этот счет?

Это сообщение отредактировал(а) Zipper - 28.4.2007, 05:15
PM MAIL   Вверх
Akella
Дата 28.4.2007, 07:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



думаю, что нет, просто FB "критично" относится к таким, можно сказать тяжёлым запросам, лучше этот запрос вставить в процедуру

Добавлено через 41 секунду
по идее процедура начинает отдавать записи ещё до того, как выполнится запрос полностью, ну или что-то в этом роде
PM MAIL   Вверх
Zipper
Дата 29.4.2007, 07:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



Цитата(Akella @  28.4.2007,  07:56 Найти цитируемый пост)
по идее процедура начинает отдавать записи ещё до того, как выполнится запрос полностью, ну или что-то в этом роде 


На полной базе (2 млн.) запрос сразу срабатывает и показывает полное отсутствие таких записей (запрос не зависает), т.е. он вообще ничего не отдает. А на маленькой базе (200-500 тыс.) находит записи.
PM MAIL   Вверх
Alex
Дата 30.4.2007, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 7
Всего: 162



Цитата(chief39 @ 27.4.2007,  19:25)
Код

select * 
from A
where A.id not in(
                             select id
                             from B
                           )

Бедный сервер да он при 2мил записях задымится от такого запроса должен был, но видимо разработчики это учли и поставили блокировку. 
А теперь разберемся по порядку:
1. Нам нужно выбрать все уникальные записи из таблицы B, мы вдруг начинаем просматривать таблицу А
2. Оператор in не использует индексированное чтение и заведомо работает крайне медлено

Протестируем запрос на таблицах с 10000 записей (под рукой с большим не оказалось)
Код

select
  B.id
from B
where B.id not in (select A.id from A)

Результат:
Код

План
PLAN (TS NATURAL)
PLAN (TL NATURAL)

Адаптированный план
PLAN (TS NATURAL) PLAN (TL NATURAL)

------ Performance info ------
Prepare time = 16ms
Execute time = 25s 843ms
Avg fetch time = 833,65 ms
Current memory = 1 265 688
Max memory = 1 291 916
Memory buffers = 4 096
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 6 786 157


Совсем немного переписав запрос:
Код

select
  B.id
from B
where not exists (select A.id from A where A.id = B.id)


Получим:
Код

План
PLAN (TS INDEX (PK_TOVAR_SVET))
PLAN (TL NATURAL)

Адаптированный план
PLAN (TS INDEX (PK_TOVAR_SVET)) PLAN (TL NATURAL)

------ Performance info ------
Prepare time = 16ms
Execute time = 31ms
Avg fetch time = 1,00 ms
Current memory = 1 282 020
Max memory = 1 291 916
Memory buffers = 4 096
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 6 431


Добавлено через 2 минуты и 47 секунд
Zipper, скажи пожалуйста, а сколько времени требовалось серверу, что бы отдать тебе результат даже для 300000 записей? Насколько я понимаю минут 6 должен был бедняга трудиться.


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Zipper
Дата 2.5.2007, 07:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



Цитата(Alex @  30.4.2007,  09:14 Найти цитируемый пост)
Zipper, скажи пожалуйста, а сколько времени требовалось серверу, что бы отдать тебе результат даже для 300000 записей? Насколько я понимаю минут 6 должен был бедняга трудиться. 


Alex, что-то около 50 сек.
Цитата(Alex @  30.4.2007,  09:14 Найти цитируемый пост)
но видимо разработчики это учли и поставили блокировку.

Так все таки блокировка существует?
Попробую твой вариант, сообщу о результатах. За ранее спасибо. Раньше работал с Oracle. Не достаточно еще разобрался с особенностями FireBird. Будем стараться.  smile 
PM MAIL   Вверх
Alex
Дата 2.5.2007, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 7
Всего: 162



Цитата(Zipper @  2.5.2007,  08:30 Найти цитируемый пост)
Так все таки блокировка существует?

Официально известно одно ограничение массив элементов для оператора in не может превышать 1500 элементов 
Цитата(Zipper @  2.5.2007,  08:30 Найти цитируемый пост)
Попробую твой вариант, сообщу о результатах. За ранее спасибо. Раньше работал с Oracle. Не достаточно еще разобрался с особенностями FireBird.

На чем бы вы не работали запрос с оператором in тяжелая операция для сервера, да еще вы заставляете при каждой проверки условия выполнить выборку всей таблицы, а вам на самом деле нужно узнать только один элемент.


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Zipper
Дата 3.5.2007, 05:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



Цитата(Alex @  2.5.2007,  10:22 Найти цитируемый пост)
а вам на самом деле нужно узнать только один элемент


Мне надо отобрать все записи id которых не встречается в другой таблице.
Я написал такой запрос
Код

select s.tab_num, s.fam, s.im, s.ot
from "1SOTRONOS" s
where not exists  (
                        select substring(c.fields from 9 for 6)
                        from cards c
                        where c.pfirm = 10 and '00000007' in (c.fields) and 
                        cast (substring(c.fields from 9 for 6) as integer) = s.tab_num
                      )

При выполнении выдается ошибка 
Arithmetic overflow or division by zero has ocurred.
arithmetic exception, numeric overflow, or string truncation.
Cannot transliterate character between character sets.

c.fields типа Blob, s.tab_num типа integer
В чем может быть дело?

Периписал запрос следующим образом
Код

select s.tab_num, s.fam, s.im, s.ot
from "1SOTRONOS" s
where not exists
                                            (
                                            select substring(c.fields from 9 for 6)
                                            from cards c
                                            where c.pfirm = 10 and '00000007' in (c.fields) and
                                            substring(c.fields from 9 for 6) like cast(s.tab_num as varchar(6))
                                            )

все заработало.
Наверно где-то в substring(c.fields from 9 for 6) были данные не конвертируемые в integer.

Это сообщение отредактировал(а) Zipper - 3.5.2007, 05:20
PM MAIL   Вверх
Zipper
Дата 3.5.2007, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



А еще одну проблему поможете решить?
Есть такой update
Код

update cards c
set fields = '00000007'||
            (
            select cast(s.tab_num as varchar(6))
            from "1SOTRONOS" s
            where s.fam = c.name1 and s.im = c.name2 and s.ot = c.name3 )
where c.pfirm=10 and substring(c.fields from 9 for 6) is null

Надо дополнить поле fields таблицы cards, если оно пустое, строчкой '00000007'+табельный_номер, который берется из поля tab_num (типа integer) таблицы "1SOTRONOS" при совпадении фамилии имени отчества. Но дело в том что встречаются полные тезки и соответственно выбираются несколько записей табельного номера, а он уникальный. как мне исклбчить такую ситуацию? Пусть выбирался бы только один из них. Второго можно поправить руками.
PM MAIL   Вверх
Akella
Дата 3.5.2007, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 20
Всего: 329



Цитата(Alex @  30.4.2007,  09:14 Найти цитируемый пост)
2. Оператор in не использует индексированное чтение и заведомо работает крайне медлено

в FB 2.0 и выше уже и in использует индексы

Добавлено @ 14:23
Цитата(Alex @  2.5.2007,  10:22 Найти цитируемый пост)
Официально известно одно ограничение массив элементов для оператора in не может превышать 1500 элементов 

да это так, но в этом случае вываливается исключение, а не так что сервер тихо блокирует...

Добавлено @ 14:25
Zipper, это по идее уже должна была быть новая тема про UPDATE

Добавлено через 13 минут и 37 секунд
Alex, если можно использовать  exists, то вообще зачем тогда in? Или in это старый оператор, так сказать и его лучше не использовать?

Это сообщение отредактировал(а) Akella - 3.5.2007, 14:25
PM MAIL   Вверх
Alex
Дата 3.5.2007, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 7
Всего: 162



Цитата(Zipper @  3.5.2007,  12:38 Найти цитируемый пост)
Надо дополнить поле fields таблицы cards, если оно пустое, строчкой '00000007'+табельный_номер, который берется из поля tab_num (типа integer) таблицы "1SOTRONOS" при совпадении фамилии имени отчества. Но дело в том что встречаются полные тезки и соответственно выбираются несколько записей табельного номера, а он уникальный. как мне исклбчить такую ситуацию? Пусть выбирался бы только один из них. Второго можно поправить руками. 

Код

update cards c
set fields = '00000007'||
            (
            select FIRST 1 cast(s.tab_num as varchar(6))
            from "1SOTRONOS" s
            where s.fam = c.name1 and s.im = c.name2 and s.ot = c.name3 )
where c.pfirm=10 and substring(c.fields from 9 for 6) is null



Цитата(Akella @  3.5.2007,  15:20 Найти цитируемый пост)
в FB 2.0 и выше уже и in использует индексы

На практике это у него не всегда получается

Цитата(Akella @  3.5.2007,  15:20 Найти цитируемый пост)
да это так, но в этом случае вываливается исключение, а не так что сервер тихо блокирует...

лично мне до сих пор слабо верится, что там тихо промолчали...

Цитата(Akella @  3.5.2007,  15:20 Найти цитируемый пост)
Alex, если можно использовать  exists, то вообще зачем тогда in? Или in это старый оператор, так сказать и его лучше не использовать?

Задачи разные у людей бывают


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Zipper
Дата 4.5.2007, 05:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 28.9.2006

Репутация: нет
Всего: нет



Цитата(Alex @  3.5.2007,  15:02 Найти цитируемый пост)
лично мне до сих пор слабо верится, что там тихо промолчали...


Вериться не вериться, а промолчал. 
То есть если SQL возвращает более 1500 тысячей записей в операторе IN ( select ...), то сервер такой запрос не выполнит и должен выдать исключение?
PM MAIL   Вверх
Alex
Дата 4.5.2007, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 7
Всего: 162



Цитата(Zipper @  4.5.2007,  06:40 Найти цитируемый пост)
То есть если SQL возвращает более 1500 тысячей записей в операторе IN ( select ...), то сервер такой запрос не выполнит и должен выдать исключение? 

Лично я не уверен, что на select в in это условие распространяется

Цитата(Zipper @  4.5.2007,  06:40 Найти цитируемый пост)
Вериться не вериться, а промолчал. 

В чем тестировался запрос?


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Interbase"
Alex

Обязательно указание:

1. Версию InterBase (Firebird, Yaffil)

2. Способа доступа (ADO, BDE, IBX и т.д.)

  • КАК ПРАВИЛЬНО ОФОРМИТЬ КОД - ЗДЕСЬ
  • КАК ПРАВИЛЬНО УКАЗАТЬ ТЕКСТ ОШИБКИ - ЗДЕСЬ
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • FAQ раздела лежит здесь!

Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Firebird, Interbase | Следующая тема »


 




[ Время генерации скрипта: 0.0687 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.