| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > 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 различия:
Нужно то же самое, но для 16 полей и 5 различий в них. |
| Автор: Alex 3.10.2005, 20:24 |
| |
| Автор: xgm 4.10.2005, 09:12 |
| Древовидные структуры организуются из двух полей одной таблицы !!! |
| Автор: Ace Wentura 4.10.2005, 11:24 | ||
И что это означает? Вопрос не в том, что я храню. Это подсказка. У меня есть база. В ней нужно сделать обновление. К сожалению, руками. Дабы упростить себе жизнь нужно подсказать, что вот такая-то запись отличается от текущей на одно поле. Для этого делается подобный запрос. Есть другие предложения? |
| Автор: Alex 5.10.2005, 11:25 | ||
Если это нужно сделать 1 раз, может выполнить несколько запросов. Тоесть не сразу все поля сравнивать, а частями? |
| Автор: SergeBS 6.10.2005, 15:14 |
| Ace Wentura Комбинаторику почитай. У тебя бешеное количество запросов выходит. Отсюда вывод - писать генератор запросов. Этой задачки тебе на недельку хватит. Может ручками проще? Или строй индекс по какому-то количеству полей и сравнивай соседние записи на разницу. Это проще. Индексов тоже построить придется немало Но работать будет долго. |
| Автор: Ace Wentura 6.10.2005, 16:37 | ||
Спасибо за совет не по теме, но: 1. Комбинаторику я почитал (иначе как бы возник такой вопрос) 2. Считать пока не разучился 3. Генератор запросов был написан за 2 часа (а не за неделю) 4. Ручками проще? Предполагаю, что 6 тысяч записей сравнить ручками не так уж и просто... 5. Про индексы - не понял. Можешь пояснить свою мысль с примерами (желательно). 6. Работает это долго и сейчас. |
| Автор: SergeBS 12.10.2005, 18:24 | ||
Пожалуста. Если не по теме, то почему генератор написал? 1. Цифирку получил - это число запросов. 2. См. п.1 3. См. вводное предложение + аксиома: "Что быстро делается, то потом медленно или плохо работает". Заодно съехидничаю: запросы каждый раз по новой строятся? 4. О количестве - только сейчас написал. Какие ко мне претензии? За компанию: 6 тыс. записей может получиться просто в массив сожрать и уже там лопатить. Это должно быть очень даже быстро. Дарю эту мысль "бесплатно, то есть даром" (с) сова. 5. "Элементарно, Ватсон". Псевдокод: Допустим, надо найти все записи, одинаковые не меньше чем по m каким-то полям. По этим полям формируем индекс. И эти же поля сравниваем. Если, например, n-ная запись отличается от n+1, то одинаковых с ней (n-ной) дальше нет. Все что были одинаковы (если были) - были раньше. Прокатываем по базе сравнивая только соседние записи. Убиваем индекс и строим следующий. Время работы - не прикидывал. Но должно быть ОЧЕНЬ большое, т.к. DBF-ный подход. Хотя если на локальной машине и впрямую (см. насчет массива) - еще вопрос. Ну где я пример найду, сам подумай. Приблуду, ищущую в таблице граждан, одинаковых по ФИО+ДР, которой лет 10 уже, на Фоксе, выслать? 6. А что конкретно долго - отдельный запрос или просто их количество переходит в "долго"? Компильнуть и в UDF - в хранимки? |
| Автор: Ace Wentura 12.10.2005, 19:58 | ||
Совет не по теме - почитать комбинаторику. (надеюсь, что на этом мы завершим ехиднеческие высказывания и высказывания в повелительно-наставительном наклонении? Насколько я помню правила форума - они здесь неприемлемы. И не нужно утирать мне нос - не первую строчку кода ваяю.) Принцип работы генератора: есть один большой запрос, который выбирает поля исходя из условия в формате: ('Поле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 | ||
Что значит зачем мне OR? И что значит написать генератор правильно? Если я правильно читал комбинаторику Необходимых полей - именно необходимых - 19. (в базе полей гораздо больше). Но интересует вовсе не это, а сравнение быстродействия базы данных с неиндексированным массивом. |
| Автор: SergeBS 14.10.2005, 15:34 | ||||
Ace Wentura
Вот твой запрос: ('Поле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*число интересующих записей. Я вначале выдрал бы из базы минимально интересные (с минимальным совпадением), а уже потом загнал в массив. Быстродействие: при запросе к БД работают ее интерпретатор, диск. Достаточно вспомнить только про диск. Впрочем интерпретатор - компилятор тоже сравнение интересное. Потому как ни исхитряйся тормозить алгоритм поиска, разница будет в порядки. Кстати в Delphi есть несколько способов работы с таблицей, загрузив ее в память. Т.е. можно даже ничего не изобретать. |