Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Firebird, Interbase > Запись с отличием в одно поле


Автор: Ace Wentura 3.10.2005, 19:56
Итак есть проблема в получении записи, которая отличается от заданной на одно (2, 3, 4, 5) поле(й).

Попробовал перебрать все варианты различий но для 16 полей и 4 вариантов FireBird отказался воспринимать. Причин понять не могу - возможно, что запрос слишком длинный.

Есть ли предложения по поводу написания подобного запроса?

Автор: Alex 3.10.2005, 20:09
ничего не понял. приведи пример запроса

Автор: Ace Wentura 3.10.2005, 20:16
Для таблицы:
Поле1, Поле2, Поле3
Запрос для 3-х полей и 1 различия:
Код
SELECT * FROM table WHERE
(Поле1='1' AND Поле2='2')
OR
(Поле1='1' AND Поле3='3')
OR
(Поле2='2' AND Поле3='3');

Нужно то же самое, но для 16 полей и 5 различий в них.

Автор: Alex 3.10.2005, 20:24
smile а что вы так изощренно храните? Ограничение помойму есть какое-то на кол-во полей в where части

Автор: xgm 4.10.2005, 09:12
Древовидные структуры организуются из двух полей одной таблицы !!!

Автор: Ace Wentura 4.10.2005, 11:24
Цитата(xgm @ 4.10.2005, 09:12)
Древовидные структуры организуются из двух полей одной таблицы !!!

И что это означает?

Вопрос не в том, что я храню. Это подсказка. У меня есть база. В ней нужно сделать обновление. К сожалению, руками. Дабы упростить себе жизнь нужно подсказать, что вот такая-то запись отличается от текущей на одно поле. Для этого делается подобный запрос.
Есть другие предложения?

Автор: Alex 5.10.2005, 11:25
Цитата(Ace @ 4.10.2005, 12:24)
Вопрос не в том, что я храню. Это подсказка. У меня есть база. В ней нужно сделать обновление. К сожалению, руками. Дабы упростить себе жизнь нужно подсказать, что вот такая-то запись отличается от текущей на одно поле. Для этого делается подобный запрос.
Есть другие предложения?

Если это нужно сделать 1 раз, может выполнить несколько запросов. Тоесть не сразу все поля сравнивать, а частями?

Автор: SergeBS 6.10.2005, 15:14
Ace Wentura
Комбинаторику почитай. У тебя бешеное количество запросов выходит.
Отсюда вывод - писать генератор запросов. Этой задачки тебе на недельку хватит.
Может ручками проще? smile
Или строй индекс по какому-то количеству полей и сравнивай соседние записи на разницу. Это проще. Индексов тоже построить придется немало smile. По очереди.
Но работать будет долго.

Автор: Ace Wentura 6.10.2005, 16:37
Цитата(SergeBS @ 6.10.2005, 15:14)
Ace Wentura
Комбинаторику почитай. У тебя бешеное количество запросов выходит.
Отсюда вывод - писать генератор запросов. Этой задачки тебе на недельку хватит.
Может ручками проще? smile
Или строй индекс по какому-то количеству полей и сравнивай соседние записи на разницу. Это проще. Индексов тоже построить придется немало smile. По очереди.
Но работать будет долго.

Спасибо за совет не по теме, но:
1. Комбинаторику я почитал (иначе как бы возник такой вопрос)
2. Считать пока не разучился
3. Генератор запросов был написан за 2 часа (а не за неделю)
4. Ручками проще? Предполагаю, что 6 тысяч записей сравнить ручками не так уж и просто...
5. Про индексы - не понял. Можешь пояснить свою мысль с примерами (желательно).
6. Работает это долго и сейчас.

Автор: SergeBS 12.10.2005, 18:24
Цитата

Спасибо за совет не по теме, но:
1. Комбинаторику я почитал (иначе как бы возник такой вопрос)
2. Считать пока не разучился
3. Генератор запросов был написан за 2 часа (а не за неделю)
4. Ручками проще? Предполагаю, что 6 тысяч записей сравнить ручками не так уж и просто...
5. Про индексы - не понял. Можешь пояснить свою мысль с примерами (желательно).
6. Работает это долго и сейчас.

Пожалуста. Если не по теме, то почему генератор написал? smile
1. Цифирку получил - это число запросов.
2. См. п.1
3. См. вводное предложение + аксиома: "Что быстро делается, то потом медленно или плохо работает". Заодно съехидничаю: запросы каждый раз по новой строятся? smile
4. О количестве - только сейчас написал. Какие ко мне претензии?
За компанию: 6 тыс. записей может получиться просто в массив сожрать и уже там лопатить. Это должно быть очень даже быстро. Дарю эту мысль "бесплатно, то есть даром" (с) сова. smile
5. "Элементарно, Ватсон". Псевдокод:
Допустим, надо найти все записи, одинаковые не меньше чем по m каким-то полям.
По этим полям формируем индекс. И эти же поля сравниваем. Если, например, n-ная запись отличается от n+1, то одинаковых с ней (n-ной) дальше нет. Все что были одинаковы (если были) - были раньше. Прокатываем по базе сравнивая только соседние записи.
Убиваем индекс и строим следующий.
Время работы - не прикидывал. Но должно быть ОЧЕНЬ большое, т.к. DBF-ный подход.
Хотя если на локальной машине и впрямую (см. насчет массива) - еще вопрос.

Ну где я пример найду, сам подумай. Приблуду, ищущую в таблице граждан, одинаковых по ФИО+ДР, которой лет 10 уже, на Фоксе, выслать?
6. А что конкретно долго - отдельный запрос или просто их количество переходит в "долго"? Компильнуть и в UDF - в хранимки?

Автор: Ace Wentura 12.10.2005, 19:58
Цитата(SergeBS @ 12.10.2005, 18:24)
Пожалуста. Если не по теме, то почему генератор написал? smile
1. Цифирку получил - это число запросов.
2. См. п.1
3. См. вводное предложение + аксиома: "Что быстро делается, то потом медленно или плохо работает". Заодно съехидничаю: запросы каждый раз по новой строятся? smile
4. О количестве - только сейчас написал. Какие ко мне претензии?
За компанию: 6 тыс. записей может получиться просто в массив сожрать и уже там лопатить. Это должно быть очень даже быстро. Дарю эту мысль "бесплатно, то есть даром" (с) сова. smile
5. "Элементарно, Ватсон". Псевдокод:
Допустим, надо найти все записи, одинаковые не меньше чем по m каким-то полям.
По этим полям формируем индекс. И эти же поля сравниваем. Если, например, n-ная запись отличается от n+1, то одинаковых с ней (n-ной) дальше нет. Все что были одинаковы (если были) - были раньше. Прокатываем по базе сравнивая только соседние записи.
Убиваем индекс и строим следующий.
Время работы - не прикидывал. Но должно быть ОЧЕНЬ большое, т.к. DBF-ный подход.
Хотя если на локальной машине и впрямую (см. насчет массива) - еще вопрос.

Ну где я пример найду, сам подумай. Приблуду, ищущую в таблице граждан, одинаковых по ФИО+ДР, которой лет 10 уже, на Фоксе, выслать?
6. А что конкретно долго - отдельный запрос или просто их количество переходит в "долго"? Компильнуть и в UDF - в хранимки?

Совет не по теме - почитать комбинаторику. (надеюсь, что на этом мы завершим ехиднеческие высказывания и высказывания в повелительно-наставительном наклонении? Насколько я помню правила форума - они здесь неприемлемы. И не нужно утирать мне нос - не первую строчку кода ваяю.)

Принцип работы генератора:
есть один большой запрос, который выбирает поля исходя из условия в формате:
('Поле1'=1 AND 'Поле2'=2) OR ('Поле1'=1 AND 'Поле3'=3) OR ('Поле2'=2 AND 'Поле3'=3)
Соответсвенно, достаточно несложная задача получить такую конструкцию имея TStringList в формате:
'Поле1'=1
'Поле2'=2
'Поле3'=3

Но, как я уже писал, в определённый момент времени всё срывается. Слишком большой запрос. Выполняется не очень долго, но и не очень быстро. На 80 тыс записей примерно секунды полторы. При этом используется 19 полей и подсчёт идёт до 2-х отличий (на 3-х - слетает)

4. Насчёт массива - может это и дельный вопрос, но для сравнения берётся не 6 тыс записей (по 19 полей), а 80 тысяч (аналогично, по 19 полей). Думаю, что массив в памяти и умрёт - всё-таки база проиндексирована, а массив нет. Хотя утверждать не берусь. (кстати, поля размером до 300 символов)

5. Пример не нужен - мысль описана достаточно.

6. пункт не вижу целесообразным в связи с иной спецификой - не много мелких запросов, а один большой.

Автор: SergeBS 14.10.2005, 12:21
Ace Wentura
Подумай, зачем тебе в запросе OR? Если генератор написать правильно, то часть, получаемая у тебя через OR, будет получена другим запросом. И только. Сразу 2 преимущества:
- быстрее работа запроса
- короче и логичнее запрос.
Недостаток - запросов будет больше. Но не удивлюсь, если суммарное время выполнения всех запросов уменьшится. OR - это плохо.

По поводу 4:
берем размер необходимых (именно необходимых, а не всех!) для сравнения полей (ну плюс id записи), умножаем на количество, сравниваем с объемом оперативки. Нужно, как я понимаю - найти похожие. Вот в массиве и найти id похожих, а потом по id - выдрать из базы. Навскидку - пусть поля - 10 кБ * 80 т. записей - 800 Мб. Ну найдешь машину с оперативкой в 1 ГБ.

Автор: Ace Wentura 14.10.2005, 13:59
Цитата(SergeBS @ 14.10.2005, 12:21)
Ace Wentura
Подумай, зачем тебе в запросе OR? Если генератор написать правильно, то часть, получаемая у тебя через OR, будет получена другим запросом. И только. Сразу 2 преимущества:
- быстрее работа запроса
- короче и логичнее запрос.
Недостаток - запросов будет больше. Но не удивлюсь, если суммарное время выполнения всех запросов уменьшится. OR - это плохо.

По поводу 4:
берем размер необходимых (именно необходимых, а не всех!) для сравнения полей (ну плюс id записи), умножаем на количество, сравниваем с объемом оперативки. Нужно, как я понимаю - найти похожие. Вот в массиве и найти id похожих, а потом по id - выдрать из базы. Навскидку - пусть поля - 10 кБ * 80 т. записей - 800 Мб. Ну найдешь машину с оперативкой в 1 ГБ.

Что значит зачем мне OR? И что значит написать генератор правильно?
Если я правильно читал комбинаторику smile , то у меня генератор написан так, что ни один OR не повторяет запрос другого OR...

Необходимых полей - именно необходимых - 19. (в базе полей гораздо больше). Но интересует вовсе не это, а сравнение быстродействия базы данных с неиндексированным массивом.

Автор: SergeBS 14.10.2005, 15:34
Ace Wentura
Цитата

Что значит зачем мне OR? И что значит написать генератор правильно?
Если я правильно читал комбинаторику  , то у меня генератор написан так, что ни один OR не повторяет запрос другого OR...

Вот твой запрос:
('Поле1'=1 AND 'Поле2'=2) OR ('Поле1'=1 AND 'Поле3'=3) OR ('Поле2'=2 AND 'Поле3'=3)
Вот 3 запроса, в сумме дающих то же самое, но короче, без OR.
('Поле1'=1 AND 'Поле2'=2)
('Поле1'=1 AND 'Поле3'=3)
('Поле2'=2 AND 'Поле3'=3)
Что непонятно? Что сумма этих запросов даст тот же результат, что и один твой?
Преимущества и недостатки уже были описаны. Вернувшись к твоей задаче получим кучу запросов вида
('Поле1'=1 AND 'Поле2'=2 AND 'Поле3'=3 AND 'Поле4'=4.... AND 'Поле10'=10
AND 'Поле11'=11)
('Поле1'=1 AND 'Поле2'=2 AND 'Поле3'=3 AND 'Поле4'=4.... AND 'Поле10'=10
AND 'Поле12'=12)
если перебор "с хвоста" раскручивать.

Генератор написать правильно - чтобы не морочиться с количеством одинаковых полей, имеет смысл вынести это количество в параметр. Для меня такой подход - правильный.
А схитрив немного и запуская выборки с минимального совпадения до максимального, можно еще ускорить процесс, работая не со всей базой, а с результатом выборки. Т.е.
если в сумме из выборок, где 3 поля совпали, искать совпадение по 4, то размер просматриваемой таблицы мал - быстрее работа.

Цитата

Необходимых полей - именно необходимых - 19. (в базе полей гораздо больше). Но интересует вовсе не это, а сравнение быстродействия базы данных с неиндексированным массивом.

Неиндексированный массив - а это что?
Тут массив размерности 19*число интересующих записей. Я вначале выдрал бы из базы минимально интересные (с минимальным совпадением), а уже потом загнал в массив.
Быстродействие: при запросе к БД работают ее интерпретатор, диск. Достаточно вспомнить только про диск. Впрочем интерпретатор - компилятор тоже сравнение интересное. Потому как ни исхитряйся тормозить алгоритм поиска, разница будет в порядки.
Кстати в Delphi есть несколько способов работы с таблицей, загрузив ее в память. Т.е. можно даже ничего не изобретать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)