| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Базы данных и репортинг > работа с dbf |
| Автор: Valior 28.1.2010, 16:24 |
| Имеется, база данных состоящая из 3 файлов dbf 1й Файл имеет структуру в 35 полей. Нужны только 3.(номер заказа, дата и телефон) 2й 3й имеют структуру в 2 поля (номер заказа и текст заказа.) Соответственно Номер заказа во всех файлах одинаковое(названия полей только разные). Так же есть текстовый файл.(телефон и текст заказа) необходимо посредством дельфи, организовать сравнение содержимого текстового файла с данной базой за определенный период. Подскажите с чего начать7 Что лучше использовать и прочее? |
| Автор: Valior 28.1.2010, 17:02 |
| Подскажите, как удалить ненужные столбцы, и обьединить 3 файла в один, но чтобы поле номер заказа было одно? |
| Автор: Данкинг 28.1.2010, 17:22 | ||
Можно ADO.
Перебором строк только. Но вообще данную задачу я бы решал на фоксе. |
| Автор: chip_and_dayl 28.1.2010, 17:39 |
| Под обьединением файлов я так понял подразумевается - обьединение трех таблиц? Тады inner в помощь А под удалением я так понял, что нужно просто вывести из всей кучи три поля? Тогда перечисление полей в Select поможет |
| Автор: chip_and_dayl 28.1.2010, 17:49 |
| Valior Все возможно. Какие компоненты используете для работы с базой? |
| Автор: Valior 28.1.2010, 17:50 | ||
DataSource1: TDataSource; DBGrid1: TDBGrid; Table1: TTable; База в Aliase. |
| Автор: chip_and_dayl 28.1.2010, 18:03 | ||
| Valior Кстати, Ado, о котором говорил Данкинг имеет аналогичный компонент AdoTable, за рядом маленьких исключений которые связаны с подключением к базе/таблице Значить для того, чтобы обьденить все три таблицы, нужен компонент Query, который подключается как и Table, только не выбирается название таблицы. Нас интересует свойство SQL, куда нужно программно или во время построения программы написать запрос:
или обьеденять через inner join В первом варианте есть минус, во всех трех таблицах должен быть существовать заказ, то есть заказ с номером 5484 должен быть и в таблице 1 и 2 и 3, в противном случае он не попадет в результат. Если в вашем случае наличие ссылки на номер заказ в какой-то таблице нет, то нужно использовать inner join Добавлено @ 18:07 Вот инфа по http://www.skillz.ru/dev/php/article-Obyasnenie_SQL_obedinenii_JOIN_INNER_OUTER.html |
| Автор: Valior 28.1.2010, 18:07 | ||
Ахха, вот обнаружил 1 свою ошибку. 2 и 3 файл, они отличаются по кол-ву. Тоесть в 2 файле 10000 записей, а в 3 всего 6000. Значит эта запись вообще не попадет? Если забежать вперед, то алгоритм такой, считали телефон из текстого файла, выполнили поиск в 1 таблице за промежуток в -90 дней назад, если телефон не найден в базе, то сохранить номер телефона и обьявление(взятые из текстогово файла) в другую базу. |
| Автор: chip_and_dayl 28.1.2010, 18:35 | ||
Аха, не попадет (тут уже нужно копать в сторону inner join). ТО есть 1 и 2 файл одинаковы (то беж каждому номеру заказу в первой таблице соответствует номер заказа во второй таблице)!?! Добавлено через 4 минуты и 26 секунд Ой, извиняюсь. Нужно копать в сторону левого или правого внешнего обьединения, то есть Left Outer Join или Right Outer Join |
| Автор: Valior 28.1.2010, 19:12 |
| Ахха, это понятно. В поле телефон, записан телефон заказчика. Но не строго, тоесть может попадаться техх-хх-хх, может х(хххх)хх-хх-хх,ну вообщем по разному. А искать перебором, это очень долго, использую вот это Table1.Locate('teefon',s,[loCaseInsensitive]); но к сожалению, не всегда точно находит.... Как быть? |
| Автор: Данкинг 28.1.2010, 19:16 | ||
Запрос на фоксе:
|
| Автор: Frees 28.1.2010, 19:18 |
привести все номера в базе к одному формату - убрать все кроме чисел, по длине номера определить нужно ли дописывать код города |
| Автор: Valior 28.1.2010, 19:41 | ||
Тоесть методом перебора? не годится... База оч большая. |
| Автор: Frees 28.1.2010, 19:44 |
можно с помощью вычислимого поля. |
| Автор: Valior 28.1.2010, 20:49 |
Это как? |
| Автор: chip_and_dayl 28.1.2010, 21:03 | ||
| Вот нашел код с помощью, которого можно убрать все символы с номера телефона кроме цифр, то есть если введено: тел. 8-(44)-222-22-22, то результат будет 80442222222
Добавлено через 1 минуту и 18 секунд Дальше номер телефона 80442222222 нужно сократить до 7 сиволов, то есть убрать код города и т.д., для этого делаем проверку на количество символов, и если длина больше 7, удаляем первые символы пока не будет 7 знаков, то есть результат 2222222 |
| Автор: Frees 28.1.2010, 21:08 |
вот как то так http://www.citforum.ru/programming/32less/les38.shtml#3 |
| Автор: chip_and_dayl 28.1.2010, 21:10 | ||
|
| Автор: Valior 28.1.2010, 21:23 |
| Ну это я и сам сообразил, просто перебирать все строки в таблице очень и очень долго. Вопрос был, про возможность как то ускорить процедуру. |
| Автор: chip_and_dayl 28.1.2010, 21:35 |
| Ну, если в вычисляемом поле, телефон будет в "голом виде", то можно использовать тот же Locate Table1.Locate('teefon',s,[loCaseInsensitive]); Только в переменную s тоже нужно передавать телефон в "голом виде" Какая будет скорость неизвестно Добавлено через 2 минуты и 30 секунд Кстати, а сколько записей в текстовом файле? |
| Автор: Valior 28.1.2010, 21:38 | ||
| Ну это я и сам сообразил, просто перебирать все строки в таблице очень и очень долго. Вопрос был, про возможность как то ускорить процедуру. Добавлено через 1 минуту и 12 секунд
На вскидку не скажу, около 5 тысяч. В базе, где происходит поиск порядко 900 тыс |
| Автор: chip_and_dayl 28.1.2010, 21:41 |
А как часто будет происходит сравнение базы данных с текстовым файлом? Добавлено через 55 секунд И будут все записи проверятся на соответствие в базе по заданному критерию !?! |
| Автор: Valior 28.1.2010, 21:42 |
| Каждую неделю, + за неделю база возрастает на 1000-2000 обьявлений. Число в текстовом файле более или менее постоянно. Вот поэтому нужно поиск осуществлять не более 90 дней с текущей даты. |
| Автор: Frees 28.1.2010, 21:44 | ||
900 тысяч уже весомое число, так что для оптимизации забудь про локейт и займись индексацией, и поиском с помощью запросов. |
| Автор: Valior 28.1.2010, 21:51 | ||||
В том то и дело, что теоретически запросы намного быстрее должны работать. Но когда я вывжу в дбгрид испобльзуя тайбл, процесс занимает сек 4-5, а когда через запрос
то намного дольше, секунд 10-15. Вот я и растрелся что то. |
| Автор: chip_and_dayl 28.1.2010, 21:53 |
| Valior Я бы тогда предложил следующее: 1. В таблице где хранится номер телефона, создать доп. поле с хранением номера телефона в чистом виде. 2. Текстовой файл закинуть в базу 3. И также добавить поле номер телефона в чистом виде Тогда вопрос, который был поставлен в начале темы решается одним запросом на обьединение,сравнение и вставку |
| Автор: Frees 28.1.2010, 21:55 |
| а возможности поменять dbf на нормальную СУБД нет? для 900 тыс это не много... |
| Автор: chip_and_dayl 28.1.2010, 21:58 | ||
В случае с поиском через запрос, оно должно быть быстрее, так как мы не будем выводить всю таблицу, а только одну запись. ТО есть, сначала читаем первую строку из текстового файла и передаем номер телефона в запрос на поиск, после чего если критерий поиск удовлетворен, то получаем одну строку, в противном случае - пусто |
| Автор: Valior 28.1.2010, 22:01 | ||
Не совсем понял мысль. Добавлено через 1 минуту и 3 секунды К сожалению нет, если только отдельными прогами перезапись в некую другую БД. |
| Автор: chip_and_dayl 28.1.2010, 22:12 | ||
| 1. Создать в таблице доп. поле, чтобы хранить телефон в виде ххххххх 2. Отказать от текстового файла. Создать таблицу с теми же полями, что хранил текстовой файл, и информацию перенести в эту же созданную таблицу 3. В таблице, которую мы создали как замену текстовому файлу хранить телефон в виде ххххххх Правда с хранением есть один нюанс, так как мы храним 7 цифр, то кода города нету, может возникнуть ситуация, когда номер телефона с Донецка, например, 0(62)-222-22-22 совпадет с номером телефона с Киева 0(44)-222-22-22. Да, теперь самое главное, для того, чтобы сравнить есть ли данные в базе, которые есть в текстовом файле (который теперь не текстовой) достаточно написать запрос следующего плана
|
| Автор: Frees 28.1.2010, 22:14 | ||
4 проиндексировать поле "Телефон в чистом виде" |
| Автор: chip_and_dayl 28.1.2010, 22:14 |
| Frees Точно. Самое главное упустил) |
| Автор: Valior 28.1.2010, 22:20 | ||
1. А разница между созданием поля и изменением уже существующего? 2. Тут есть проблема. Данный файл мы получаем, после работы программы FineReader, тоесть будут еще процедуры для преобразования в надлежащий вид. но думаю, что можно потом будет перенести в БД 3.Можно А вот ньюанс очень критичный, тк, телефоны действительно межрегиональные. но думаю, не составит особо труда хранить и 12 цифр |
| Автор: chip_and_dayl 28.1.2010, 22:31 | ||||
Разница в том, что нам не нужно будет его гонять туда и сюда. Так как мы в виде ххххххх храним для базы, а для пользователя отображаем в удобном виде, в котором он записал.
Тогда постоянно загонять с текстового файла данные в базу, после чего очистить текстовой файл Добавлено @ 22:33
Можно 12, но если он в базе хранится в виде тел. 478-77-44, а в текстовом файле записан как 044-478-77-44, то на выходе будут разные значения. Тут такой вопрос, код города все пишут!?! или есть люди, которые записывают без кода города? |
| Автор: Valior 28.1.2010, 22:58 |
| А, все дошло, тоесть одно поле в отором будем хранить еще и голой телефон, все понял. В базе поле телефон имеет длину 12 символов. И код города только в случае, если он не родной город. А из текстового файла запись производить в новую таблицу? Как лучше? И что значит индексировать? Про это можно поподробнее? Офтоп, dbmemo1.text:=(Текст из колонки 'номер', в веделенной в дб гриде строке), как это сделать? чет не могу найти нужное... |
| Автор: chip_and_dayl 28.1.2010, 23:04 | ||||||||
Если Дбгрид отображает результат Квери, то
если ДбГрид выводит набор данных с Табле, то Квери1 заменить на Табле1 Добавлено @ 23:08
Аха. Первый храним для пользователя, а второй для сравнения данных
Все-таки нужно найти оптимальную длину, на которую нужно усекать телефон, то есть нам нужно оставить главные цифры, код и номер телефона, если минимальный код страны 2 символа, а номер телефона 7, то выходит 9. Для чего это я говорю, код города я так понял пишут, но вот код страны, могут написать и могут не написать, тогда выйдет разная длина |
| Автор: Valior 28.1.2010, 23:14 | ||
Там еще пишут и сотовые. |
| Автор: chip_and_dayl 28.1.2010, 23:20 |
| Valior Ну, сотовый тоже имеет 7 цифр - сам номер, и 2 цифры код оператора 9 цифр должно хватить, чтобы телефоны следующего плана были равны: 38(код страны) 78(оператора/города) 545 56 55 = 78 545 56 55 38(код страны) 068(оператора/города) 545 51 11 = 68 545 51 11 38(код страны) 378(оператора/города) 545 56 55 = 78 545 56 55 096 787 77 05 = 96 787 77 05 |
| Автор: Valior 28.1.2010, 23:26 |
| Ок, согласен) Щас уже проверить не смогу, забыл с работы захватить файлы. Но подведем итог. Сделать в таблице поле, и записать в него чистый номер. Создать таблицу для Текстового файла, и записать в нее его содержимое,номер - чистый |
| Автор: chip_and_dayl 28.1.2010, 23:29 |
| Valior Итог утверждаю :) Уже и время позднее, чтобы проверять. Да и работы здесь не на час :) |
| Автор: Valior 29.1.2010, 11:02 |
| Query1.SQL.Text:='INSERT INTO base (phone) ' пытаюсь вставлять в поле с "чистым номером", результат выполнения процедуры nomer, как это оформить? |
| Автор: Frees 29.1.2010, 11:18 | ||
Добавлено через 1 минуту и 44 секунды а если ты хочеш в уже добавленной записи дописать "чистый номер" то тебе нужен update а не insrt |
| Автор: Valior 29.1.2010, 11:36 | ||
создано чистое поле, я в него хочу скопировать то, что уже в другом поле, но с необходимыми изменениями. Query1.ParamByName('phone').Value := nomer; это тож понятно, как передавать в процедуру в виде входного параметра, результат селекта? |
| Автор: Frees 29.1.2010, 12:19 | ||||
тебе нужен UPDATE
|
| Автор: Valior 29.1.2010, 12:44 |
| id и phone что за поля? У меня есть old_number и new_nomber |
| Автор: Frees 29.1.2010, 12:51 |
id - первичный ключ, можно вместо него old_number использовать phone - это new_nomber |
| Автор: Valior 29.1.2010, 13:29 |
| 10 минут ждал, чтобы погляеть)))) записывает во все строки, первое переведенное значение))) |
| Автор: Frees 29.1.2010, 14:03 |
Что бы не ждать допиши в селект FIRST 20 - обработается только 20 первых записей... это как? old_number | new_nomber 234-65-23 |2346523 123-434-2 |2346523 213-3-444 |2346523 так? код свой скопируй сюда |
| Автор: Valior 29.1.2010, 14:24 |
| Разобрался, сам ошибся. Для удобства удалил все дубли из базы. и немного ее сократил. Так, вопрос, как ограничить в запросе вывод записей, до 90 дней назад? Формат даты - xx.xx.xxxx |
| Автор: Frees 29.1.2010, 14:39 | ||
date_1 поле с датой записи |
| Автор: Valior 29.1.2010, 14:46 | ||
Решил прибегнуть к такому
|
| Автор: chip_and_dayl 29.1.2010, 19:59 |
| Valior Вижу весь в поту и работе Кстати, по поводу ограничения до 90 дней, лучше сделай, как написал Frees, если не хочешь вручную отсчитывать |
| Автор: Valior 29.1.2010, 20:42 | ||
Тут мысль возникла. Если я все арвно искать буду по 90 дней сроку, может както и базу обрезать? Чтобы весь обьем то не грузить? |
| Автор: chip_and_dayl 29.1.2010, 20:46 |
| Valior То есть, в базе хочешь хранить данные за 90 дней? А то, что выше, хранить в архивной базе? |
| Автор: Valior 29.1.2010, 21:05 | ||
Я не могу указать что в ней хранить, файл базы я копирую отдельно в раб область. Файл весит 480мб. Чтобы его весь загрузить это очень много времени занимает. А область поиска каждый день ограничена 90 днями. Тоесть, прогу запустили, скопировали файл базы, обрезали его до 90 дней и начинаем с ним дальше работать. Как то так. |
| Автор: chip_and_dayl 29.1.2010, 21:40 | ||
| Valior Тады все можно обрезать одним запросом
Добавлено через 1 минуту Ты копируешь базу, делаешь этот запрос, и оно лишнее с базы удаляет |
| Автор: Frees 29.1.2010, 22:01 |
| можно сделать селект в новую таблицу(синтаксис не помню, поищи). а старую грохнуть. может быть быстрее. |
| Автор: Данкинг 2.2.2010, 00:54 | ||
Ты собрался из DBF таким образом удалять?
- правда, я не пробовал, как сиё будет работать не из фокса. |
| Автор: Valior 2.2.2010, 09:21 |
| И как это сделать? тоесть что быстрее будет? выборка или удаление и последуящая загрузка? |
| Автор: Valior 2.2.2010, 12:41 |
| Собственно программа почти написана, осталось привести к нужному виду файл. Вот такой текстовый файл мы имеем. распознается документ хренова, и всегда по разному. но думаю, что все должно свестись к виду. 1.считали строку от пустой строки до пустой строки. 2.ищем (Тел.) 3.Копируем все после п.2 до ближайщей точки. (как раз номер телефона.)+ выполняем вышенаписанную процедуру nomer и записываем кудато 3.копируем, все что выше п2. до ново строки.- будет текст тоже записываем куда то... Правильно? |
| Автор: Frees 2.2.2010, 13:23 |
| тебе этот файл разобрать надо в выше сказанную структуру? Добавлено через 55 секунд это процентов 90 от написания проги... ты только начал ее писать.. |
| Автор: Valior 2.2.2010, 13:30 |
| Не, это на самом деле мелочи)) ну от помощи бы не отказался, можно даже и советом) |
| Автор: Frees 2.2.2010, 13:39 |
| это объявления из газеты? |
| Автор: Valior 2.2.2010, 13:42 |
| Почти. |
| Автор: Frees 2.2.2010, 13:55 |
| начни с того что отдели одно объявление от другого.... как - хз... может проще распознавать не в текстовый файл а в ехель, если возможно... Исходный скрин показать можешь? |
| Автор: Valior 2.2.2010, 14:14 | ||
вот. |
| Автор: chip_and_dayl 2.2.2010, 16:16 | ||
Ну, на сколько я понял, он делает копию дбф файла, чтобы лишнее не мешало, мы его удаляем из копию базы Думал тоже предложить
|
| Автор: Valior 3.2.2010, 16:07 | ||
пытаюсь искать в таблице нужный телефон, но прога вываливается с ошибкой Operation not applicable В чем может быть сыр бор? |
| Автор: Akella 6.2.2010, 16:18 | ||
| Я смотрю, что здесь уже такой сыр-бор начался. Тему пора закрывать. Добавлено через 3 минуты и 37 секунд Valior, 1 для парсинга текста советую использовать регулярные выражения.
Мало информации. Может проблема в другом месте? А что ты надыбал в гугле по тексту ошибки?? |
| Автор: Данкинг 7.2.2010, 00:49 | ||
Это не моя цитата! Что-то с типами полей не так. |