| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > MS Access > Запрос - "типа биллинга" |
| Автор: Andrei_V 28.8.2007, 06:55 |
| Имеются таблицы (для простоты структура таблиц сокращена) 1 таблица "ack_cdr" (данные о телефонных звонках): Кому - тип текстовый (набранный номер, например "83425651357") Длительность - числовой (длительность разговора в секундах, например 36) 2 таблица "ТЛФ - Коды" (коды городов): префикс - тип текстовый (префикс города, куда был звонок, например "8342") тарифная зона - тип текстовый (тарифная зона, к которой относится префикс, например "Россия 2") 3 таблица "ТЛФ - Зоны" (тарифные зоны): тарифная зона - тип текстовый (тарифная зона, например "Россия 2") тариф - тип числовой (стоимость в руб минуты звонка в эту зону, например 5) Надо провести обработку файла cdr и определить стоимости звонков. Проблема в том, что в таблице codes есть префиксы 8342 - пермская область и 8 - россия Причем префиксы имеют произвольную длину - от 1 до 6 символов Если делать выборку конструктором с условием выборки WHERE ((ack_cdr.[Длительность])>0) AND ((ack_cdr.Кому) Like [ТЛФ - Коды].[Префикс] & "*") то, например звонок на номер "83425651357" тарифицируется дважды: как "8 - россия" и как "8342 - пермская область". Разумеется такой звонок надо протарифицировать только по префиксу с максимальной длиной (т.е. по "8342"). Как написать запрос, чтобы обработка проводилась по префиксу максимальной длины? Заранее благодарен за подсказки. |
| Автор: kapbepucm 28.8.2007, 08:55 |
| Следующий шаг, сделать группировку по номеру, где Len(вытащенного_префикса) максимален. |
| Автор: Andrei_V 28.8.2007, 09:04 |
| Слишком общий совет. |
| Автор: Andrei_V 29.8.2007, 08:31 | ||
В этом-то и основная сложность. :( |
| Автор: Akina 29.8.2007, 08:44 | ||
Если ты не можешь написАть вменяемый алгоритм отделения префикса от номера - не проси этого от программы. И вообще - пока нет алгоритма, код писАть бессмысленно. Программа - дура, и делает только то и так, что и как ты ей сказал делать.
А что, есть звонки, где "8", а потом сразу номер? |
| Автор: kapbepucm 29.8.2007, 09:18 | ||
C алгоритмом помочь?
|
| Автор: bopoha 29.8.2007, 23:50 | ||||||
| kapbepucm, Я в шоке! Все намного проще.
Основной тормоз тут MoveLast после открытия. И еще, зачем эта функция? Походу такое можно и в запрос засунуть. Andrei_V, Под "определить стоимости звонков" понимается записать в поле какой-то таблицы сумму. То получается, что посчитать это будет проще процедурой VBA, чем зарпосом (При его помощи можно оптимизировать вычисления). Тарифы телефонных кодов можно закешировать (Collection или Recordset статический) - летать будет .
Почему это сложность? Если в цикле обрабатывать номера, то можно делать разбор номера по шаблону.
Примерный алгоритм: 1. Цикл по номерам 1.1. Выделить из номера код 1.2. Получить тариф звонка 1.3 Расчитать стоимость ..... |
| Автор: kapbepucm 30.8.2007, 09:07 | ||
Частично взяв идеи bopoha, коррекция (хотя я предупреждал, что вариант неидеальный):
To bopohaБыл у меня случай, где я долго искал ошибку (там этим способом определялось количество записей, но Recordset другого типа, естественно), так теперь это, как рефлекс |
| Автор: bopoha 31.8.2007, 01:19 | ||||||||
Вариант номер 1.
На открытие таблицы тратится куча времени! Где-то перед задолго до многочисленного вызова функции откываем набор как статический (т.е. все данные читаем в память):
Если оставаться при предыдущем варианте следовало бы открывать как dbOpenForwardOnly - для прохода один раз. Вариант номер 2. Если исходить из того факта, что нужны не все коды. Их в таблице гораздо больше, чем сравниваемых. То: В.2.1. Отфильтровать набор при открытии по возрастанию кодов. Перед поиском находить запись по первой цифре искомого номера. В.2.1. Открывать набор в функции с фильтром по первой цифре номера (или минимальному количеству цифр).
Это не объясняет назначение функции. Меня интересует что она даст? Зачем она? Т.е. подразумевается ответ: "Функция получает ... находит .... и возвращает ....". На тему статического набора я пример привел. По поводу Collection
При этом нужно учитывать что Collection находится в памяти и не стоит туда загянять очень много. Естественно все это будет работать при вычислении в коде. |
| Автор: Andrei_V 31.8.2007, 08:51 | ||
Номера все имеют вид 8-код_города_номер. Но дело в тарифах. Например (очень упрощенно): 83422 - 1 руб/мин 83512 - 2 руб/мин остальная 8 - 3 руб/мин
Как-то не силен я пока код писать в MS Access. До сих пор делал все конструкторами - таблицы, запросы, отчеты. Большего не требовалось. И мне казалось, что и мою задачу можно решить не прибегая к непосредственному написанию кода на VB. Функция-то ясна. Сам был программистом, правда лет 10 назад. |
| Автор: kapbepucm 31.8.2007, 09:14 | ||
To bopohaСлучай был подобным:
To Andrei_VА где и как данные будут выводится (вырисовывается 2 варианта: лёгкий, но тормознутый; и более сложный, но быстро летающий)? |
| Автор: Akina 31.8.2007, 12:04 | ||||
ДЛя ускорения работы надо использовать
Тогда можно просто бежать по рекордсету до первого совпадения - все следующие будут с заведомо более коротким префиксом. И не потребуется использования Like - можно сразу
|
| Автор: Andrei_V 5.9.2007, 14:21 | ||
Кратко об обоих вариантах можно узнать? Пока выводится просто как результат запроса в виде таблицы в среде MS Access |
| Автор: bopoha 5.9.2007, 23:28 |
| До меня дошел алгоритм поиска тарифа за код: Начинать поиск нужно с самого длинного кода (84320), если не найден убрать одну цифру ((84320) поискать. Если опять не нашли повторить. Правильно? Очень рекомендую разобраться с VBA, такое просто запросами тяжеловато. 1. Можно отдельной функцией реализовать выше указанный алгоритм и в запросе вызывать ее, передвая функции код. Это очень медленный вариант. 2. Либо программно все сделать. Это вариант будет быстрее. Ничего сложного в этом нет. |
| Автор: kapbepucm 10.9.2007, 14:21 |
| bopoha, второй вариант оказывается относительно быстрее. А что, если данные о произведённых звонках дополняютя 1 раз в 5 секунд, а запросы надо делать тоже часто? |
| Автор: bopoha 11.9.2007, 23:04 |
| Какая стоит задача? Если есть возможность, то вообще идеальным было бы при добавлении и расчитывать стоимость. В противном случае, только перед использованием стоимости звонков. Расчитывать же можно только звонки без сумм. |