|
v7: Файлы dbf, ключи, индексы | ☑ | ||
---|---|---|---|---|
0
BalBess
23.05.16
✎
10:47
|
Кто силен в dbf подскажите (в поисковиках не нашел реальных примеров)
Задача следующая: Есть dbf - таблица, с 2 полями: товар и цена нужно отобрать из нее товары с определенной ценой, например 100р Есть метод Найти(), но как я понял ищет одну (первую) запись, а как найти все записи по условию? |
|||
1
Mikeware
23.05.16
✎
10:50
|
НайтиПоКлючу, а дальше перебирать, пока не конец файла.
Это если чисто дибейсик |
|||
2
lubitelxml
23.05.16
✎
10:51
|
загрузи в тз и разбери ее как тебе надо
|
|||
3
Mikeware
23.05.16
✎
10:53
|
(2) зачем лишние телодвижения? индексированный дбф и так достаточно быстр...
|
|||
4
BalBess
23.05.16
✎
10:58
|
(1) а нет примерчика, не разу с dbf не работал
в СП написано: "Найти запись по индексу". (Запись - в единственном числе), и еще "Перед вызовом метода следует установить значения всех атрибутов агрегатного объекта типа ''Ключ'', которые участвуют в вычислении выражения текущего индекса." Эта фраза вообще не понятна, для меня (2) мне как раз надо наоборот, через ТЗ долго (3) поле цена у меня индексное предлагаете просто перебором? ДБФ.Первая(); Пока 1 = 1 Цикл Если ДБФ.Следующая() = 0 Тогда Прервать; КонецЕсли; Если ДБФ.PRICE <> Цена Тогда Продолжить; КонецЕсли; Сообщить(ДБФ.NAME); КонецЦикла; так работает, но я думал через ключи/индексы будет намного быстрее |
|||
5
BalBess
23.05.16
✎
11:02
|
Опишу задачу, кассир вводит в поле "цена" - цену
Нужно чтобы по нажатию каждой кнопки, чтобы перезаполнялась таблица. Т.е. в реальном режиме, а товаров около 40000 Я пробовал, через перебор/удаление не нужных позиций из ТЗ уходит 300мс, через цикл по dbf - и заполнение ТЗ заново - где-то 100мс Хочу еще сократить это время, т.к. компы на кассах "не шустрые" |
|||
6
ДенисЧ
23.05.16
✎
11:05
|
Анафея каждый раз читать весь файл? Загрузить и оперировать им не?
|
|||
7
BalBess
23.05.16
✎
11:11
|
(6) загружается dbf файл один раз, при запуске 1с
Как им "оперировать"? как найти ВСЕ записи по условию (например цене) |
|||
8
Mikeware
23.05.16
✎
11:13
|
ДБФ.ДобавитьИндекс("Price","Price",0,0)
ДБФ.Price=1000 Если ДБФ.НайтиПоКлючу(1) тогда ДБФ.ХХХ - первая запись с равным или больше ключом пока ДБФ.ВКонце()=0 цикл ДБФ.ХХХ - остальные записи с равным или больше ключом |
|||
9
Mikeware
23.05.16
✎
11:17
|
+(8) Пардон...
ДБФ.КЛЮЧ.Price=1000 |
|||
10
BalBess
23.05.16
✎
11:22
|
(8) сорри конечно, но до меня не доходит, как теперь достать все записи из него
что значит ДБФ.ХХХ |
|||
11
BalBess
23.05.16
✎
11:28
|
Еще просит перед использованием индекса указать индекс, т.е. пока такая конструкция получилась
ДБФ.ДобавитьИндекс("IDXPRICE","PRICE",0,0) ДБФ.ТекущийИндекс("IDXPRICE"); ДБФ.КЛЮЧ.PRICE=Цена; Если ДБФ.НайтиПоКлючу(0) > 0 тогда // ДБФ.ХХХ - первая запись с равным или больше ключом // пока ДБФ.ВКонце()=0 цикл // ДБФ.ХХХ - остальные записи с равным или больше ключом КонецЕсли; |
|||
12
Mikeware
23.05.16
✎
11:29
|
(10) Ты не "все" достаешь, а по очереди.
после НайтиПоКлючу - у тебя либо конец файла, либо выборка записей |
|||
13
Mikeware
23.05.16
✎
11:30
|
(11) после установки индекса вроде надо передернуть позицию.
сделай, например, .Первая() |
|||
14
BalBess
23.05.16
✎
11:53
|
(12) все-равно не получается ((
ДБФ.ТекущийИндекс("IDXPRICE"); ДБФ.Первая(); Цена = 100; ДБФ.КЛЮЧ.PRICE=Цена; Если ДБФ.НайтиПоКлючу(0) > 0 тогда // ДБФ.ХХХ - первая запись с равным или больше ключом пока ДБФ.ВКонце()=0 цикл // ДБФ.ХХХ - остальные записи с равным или больше ключом Сообщить(ДБФ.NAME); ДБФ.Следующая(); КонецЦикла; КонецЕсли; Выходят все поля, а не только с ценой 100 |
|||
15
BalBess
23.05.16
✎
11:58
|
Вернее выходят поля у которых цена БОЛЬШЕ или равна 100
и работает горазззздо дольше, 2100мс |
|||
16
Mikeware
23.05.16
✎
11:59
|
(14) ДБФ.НайтиПоКлючу(0)- ищет точное соответсвие
|
|||
17
BalBess
23.05.16
✎
12:10
|
(16) ну да! сам удивляюсь
пробовал ДБФ.НайтиПоКлючу("="), то-же самое и самое главное: работает гораздо дольше |
|||
18
BalBess
23.05.16
✎
12:25
|
набросал тест, может кто у себя проверить?
Процедура Сформировать() ДБФ = СоздатьОбъект("XBase"); ДБФ.ДобавитьПоле("NAME", 2, 100, 0); ДБФ.ДобавитьПоле("PRICE", 1, 8, 2); //ДобавитьИндекс(<Название>, <Выражение>, <Уникальность>, <Убывание>, <Фильтр>) ДБФ.ДобавитьИндекс("IDXPRICE", "PRICE", 0, 0, ""); ДБФ.СоздатьФайл("c:\temp\goods.dbf", "c:\temp\goods.cdx"); ДБФ.ОчиститьФайл(); ДБФ.Добавить(); ДБФ.NAME = "Булка хлеба"; ДБФ.PRICE = 20; ДБФ.Записать(); ДБФ.Добавить(); ДБФ.NAME = "Два кусочека колбаски"; ДБФ.PRICE = 100; ДБФ.Записать(); ДБФ.Добавить(); ДБФ.NAME = "Коньяк Арарат"; ДБФ.PRICE = 1000; ДБФ.Записать(); ДБФ.Переиндексировать(); ДБФ.ТекущийИндекс("IDXPRICE"); ДБФ.Первая(); Цена = 100; ДБФ.КЛЮЧ.PRICE=Цена; Если ДБФ.НайтиПоКлючу("=") > 0 тогда // ДБФ.ХХХ - первая запись с равным или больше ключом пока ДБФ.ВКонце()=0 цикл // ДБФ.ХХХ - остальные записи с равным или больше ключом Сообщить("" + ДБФ.NAME); ДБФ.Следующая(); КонецЦикла; КонецЕсли; КонецПроцедуры |
|||
19
BalBess
23.05.16
✎
12:37
|
добавил простой перебор
даже на таком простом примере видно что перебор работает быстрее. У меня 4мс, против 1мс //******************************************* Процедура Сформировать() ДБФ = СоздатьОбъект("XBase"); ДБФ.ДобавитьПоле("NAME", 2, 100, 0); ДБФ.ДобавитьПоле("PRICE", 1, 8, 2); //ДобавитьИндекс(<Название>, <Выражение>, <Уникальность>, <Убывание>, <Фильтр>) ДБФ.ДобавитьИндекс("IDXPRICE", "PRICE", 0, 0, ""); ДБФ.СоздатьФайл("c:\temp\goods.dbf", "c:\temp\goods.cdx"); ДБФ.ОчиститьФайл(); ДБФ.Добавить(); ДБФ.NAME = "Булка хлеба"; ДБФ.PRICE = 20; ДБФ.Записать(); ДБФ.Добавить(); ДБФ.NAME = "Два кусочека колбаски"; ДБФ.PRICE = 100; ДБФ.Записать(); ДБФ.Добавить(); ДБФ.NAME = "Коньяк Арарат"; ДБФ.PRICE = 1000; ДБФ.Записать(); ДБФ.Переиндексировать(); Начало = _GetPerformanceCounter(); //зафиксируем начало процесса... ДБФ.ТекущийИндекс("IDXPRICE"); // ДБФ.Первая(); Цена = 100; ДБФ.КЛЮЧ.PRICE=Цена; Если ДБФ.НайтиПоКлючу("=") > 0 тогда // ДБФ.ХХХ - первая запись с равным или больше ключом пока ДБФ.ВКонце()=0 цикл // ДБФ.ХХХ - остальные записи с равным или больше ключом Сообщить("" + ДБФ.NAME); ДБФ.Следующая(); КонецЦикла; КонецЕсли; Конец = _GetPerformanceCounter(); //зафиксируем окончание процесса... Сообщить("" + (Конец - Начало)); //вычислим время выполнения цикла в секундах. // простой перебор Начало = _GetPerformanceCounter(); //зафиксируем начало процесса... ДБФ.Первая(); Пока 1 = 1 Цикл Если ДБФ.Следующая() = 0 Тогда Прервать; КонецЕсли; Если ДБФ.PRICE <> Цена Тогда Продолжить; КонецЕсли; Сообщить("" + ДБФ.NAME); КонецЦикла; Конец = _GetPerformanceCounter(); //зафиксируем окончание процесса... Сообщить("" + (Конец - Начало)); //вычислим время выполнения цикла в секундах. КонецПроцедуры |
|||
20
Mikeware
23.05.16
✎
12:49
|
(19) естественно, тупой перебор быстрее. а теперь перебери пару миллионов записей...
|
|||
21
BalBess
23.05.16
✎
12:55
|
(20) ну фиг его знает, я проверял на 40тыщ записей
поиск по ключу 2100мс, а перебор 100мс на 3 записях я еще поверю, установка ключей, поиск и т.д. но не на 40тыщ - же И самое ГЛАВНОЕ: не находит точное соответствие ключу! |
|||
22
Mikeware
23.05.16
✎
13:14
|
(21) значит, что-то с руками.
у меня работало |
|||
23
BalBess
23.05.16
✎
13:45
|
(22) мож и руки конечно, но код-же я привел..
мож там какой команды не хватает или может НайтиПоКлючу() для поиска одной записи.. есть у кого мысли, по этому поводу ) |
|||
24
Ёпрст
23.05.16
✎
13:46
|
(0) на вот, наслаждайся
https://cloud.mail.ru/public/ED6T/M7DrVqnxT Тупо запрос к файлику и там что угодно - группировки, фильтры и т.д |
|||
25
NorthWind
23.05.16
✎
13:49
|
(0) если стандартными средствами, то по-моему, там только нафигационный метод. Т.е. найти первую запись и дальше пока условиям поиска удовлетворяет.
Ну или если так неохота, тогда можно попробовать открыть средствами ADO (провайдер MS Jet) и дальше обычный SQL. Я, правда, так не пробовал, но не вижу, почему бы могло не получиться. |
|||
26
NorthWind
23.05.16
✎
13:52
|
вот здесь описана строка коннекта ADO+MS Jet 4.0 для файлов dbf:
https://support.microsoft.com/ru-ru/kb/326548#bookmark-3 |
|||
27
BalBess
23.05.16
✎
14:00
|
(24) (25) (26) не знаю, нужно-ли настолько все усложнять
и будет-ли это работать быстрее простого перебора это програмка будет стоять на старых машинах с WinXP в принципе там все работает, кроме поиска по цене "реал-тайм", сейчас работает по принципу, набрал цену, нажал поиск а я хочу набрал цифру 1, вывелись товары с ценой 1р, нажал 0, вывелись товары с ценой 10р, и т.д. |
|||
28
Mikeware
23.05.16
✎
14:06
|
(27) поклади куданить файлик, посмотрю...
|
|||
29
Ёпрст
23.05.16
✎
15:11
|
(27) будет работать быстрее, если будет задействован подходящий индекс
|
|||
30
Ёпрст
23.05.16
✎
15:12
|
ну а просто уссловие, для такого маленького файла, это милисекунды
|
|||
31
Mikeware
23.05.16
✎
15:27
|
(30) ну 40 тыщ записей - всяко быстрее, чем перебор должно быть...
|
|||
32
Djelf
23.05.16
✎
22:32
|
dbf... dbf...
1sqlite, 770к записей (загруженная из xml база алкогольных лицензий), отбор 618 записей по индексу инн - 160мс на холодную базу (полный перезапуск компа) и 2мс на горячую |
|||
33
BalBess
24.05.16
✎
09:35
|
Сорри за задержку..
(28) http://файлообменник.рф/s5ueadz6bx1w.html попробуйте отсюда скачать, если не получиться пишите (32) я понимаю что вариантов реализации множество, в 1с77 встроенна поддержка dbf, мне нужно чтобы работало из коробки. Програмка простенькая, не хочу ее наворачивать 1sqlite, ADO+MS Jet 4.0 и иже с ними. |
|||
34
BalBess
24.05.16
✎
09:41
|
(28) либо вот
https://cloud.mail.ru/public/JQp4/K23EjSE8Y это файлик без индексов, там продукты, еще есть такой-же хозтовары, но я думаю хватит одного для тестов |
|||
35
BalBess
24.05.16
✎
11:39
|
Кажется разобрался.
В общем метод НайтиПоКлючу() - видимо сортирует таблицу по этому ключу, и устанавливает указатель на первую запись Если в цикле вставить проверку на этот ключ, то все начинает работать на порядок быстрее. Без проверки время было 2000мс, с проверкой 5-10мс. Напомню прямым перебором у меня было 100мс ДБФ.ТекущийИндекс("IDXPRICE"); ДБФ.КЛЮЧ.PRICE=Цена; Если ДБФ.НайтиПоКлючу("=") > 0 тогда // ДБФ.ХХХ - первая запись с равным или больше ключом пока ДБФ_товары.ВКонце()=0 цикл // ДБФ.ХХХ - остальные записи с равным или больше ключом Если ДБФ.PRICE > Цена Тогда Прервать; КонецЕсли; Сообщить(ДБФ.NAME); ДБФ.Следующая(); КонецЦикла; КонецЕсли; |
|||
36
BalBess
24.05.16
✎
11:41
|
Всем большое спасибо! как всегда форум выручил))
|
|||
37
Mikeware
24.05.16
✎
12:01
|
(35) он не сортирует по ключу - он строит индекс. Ну, типа сортировки, да...
но вроде при поиске по ключу по равенству - должен выбирать только равные, и заканчивать выборку по еоф. ДБФ.НайтиПоКлючу("=") - не знаю попробуй как в СП, ДБФ.НайтиПоКлючу(0) |
|||
38
BalBess
24.05.16
✎
12:43
|
(37) я пробовал и так и так, эффект тот-же
я думаю так, он же не может удалить записи из таблицы (те которые не проходят по условию). Просто он упорядочивает их (по ключу), и ставит указатель на первый. Т.е. в таблице остаются ВСЕ записи, только отсортированные, остается выбрать нужные )) Если взять все записи после НайтиПоКлючу(0), то видно что они отсортированные именно по цене становятся |
|||
39
Bigbro
24.05.16
✎
12:58
|
у меня был такой же результат как в (35) прерывать приходилось по условию.
|
|||
40
Mikeware
24.05.16
✎
13:13
|
ну, значит я все уже позабыл нафик...
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |