![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
![]() Есть база данных access, в ней две таблицы
1) Ведомость на отгрузку - дата,Направление, расстояние,перевозчик, подтверждение 2) Перевозчик - название, процентная доля Надо в первой таблице отсортировать записи по расстоянию, в 4 категории 1 - до 200км, 2- 200-400км, 3 - 400-600км, более 600км Записям до 200 км - поставить в поле перевозчик занчение - компания Остальные поля "перевозчик" надо автоматически распределить между компаниями перевозчиками, в соот с их долями (доли указаны в процентах во второй моей таблице) Вот в общем в чем пробема, помогите пожалуйста уже голову сломал, даже в какую сторону думать не знаю, если нужны какие либо уточнения тут же отпишу |
#2
|
||||
|
||||
![]() Код:
Table1.First; while Table1.Eof do begin if Table1.FieldByName('RAST').Integer<=200 then begin Table1.Edit; Table1.FieldByName('PEREVOZ').String:='Компания'; Table1.Post; end; Table1.Next; end; Поживу - увижу, Доживу - узнаю, Выживу - учту. ![]() [P.S.]->Выражая благодарность за помощь - Вы получаете шанс на помощь в следующий раз
|
#3
|
|||
|
|||
![]() Прости моя ошибка, проблема в том что пишу это дело все на delphi, и работаю с компонентами ado для отображения следовательно dbgrid использую
|
#4
|
|||
|
|||
![]() Прости моя\ ошибка, клиент пишу на делфи использую компоненты ado, для отображения dbgrid, как в этом случае это написать, поясни пожалуйста
|
#5
|
|||
|
|||
![]() Первое - группировка, не знаю, прокатит или нет, но можно попробовать.
Код:
SELECT RASSTOYANIE, PEREVOZCHIK, CASE WHEN RASSTOYANIE <= 200 THEN 1 WHEN RASSTOYANIE > 200 AND RASSTOYANIE <= 400 THEN 2 WHEN RASSTOYANIE > 400 AND RASSTOYANIE <= 600 THEN 3 ELSE 4 END AS CATEGOTIYA FROM VEDOMOST SORT BY CATEGOTIYA -- Если здесь не возьмет, то сортировать по полю RASSTOYANIE -- Это не имеет значения Это получение. Такой запрос можно и группировать. Теперь что по поводу установки. Фактически, тебе надо посчитать кол-во элементов и поделить их в соотв. пропорции (кстати, а у тебя в таблице перевозчиков суммарная доля не больше 100%?). Тут делаем в несколько шагов. 1. Устанавливаем всем расстояниям <= 200 значение "компания" (делаем запросом, что бы не нагружать сеть - пусть СУБД трудится): Код:
UPDATE VEDOMOST SET PEREVOZCHIK = 'компания' WHERE RASSTOYANIE <= 200 2. Теперь нам надо установить общее кол-во записей для распределения по другим перевозчикам. Опять же делаем всего 1 запрос: Код:
SELECT count(*) FROM VEDOMOST WHERE RASSTOYANIE > 200 Фактически мы получим кол-во неустановленных строк. Здесь маленнькая ремарка. В эти 2 выборки не попадут ведомости, у которых значение расстояния не установлено, т.е. равно NULL. Что бы их добавить в тот или иной запрос, надо в конце добавить "OR RASSTOYANIE IS NULL" (без кавычек, соответсвенно). 3. Теперь нам надо посчитать сколько на 1% доли перевозчиков приходится записей в ведомосях. Здесь, во первых, стахуемся от того, что суммарная доля м.б. > 100%. Да, предполагаем, что там у тебя хранятся проценты, т.е. числа от 0 до 100. Код:
SELECT SUM(DOLYA) FROM PEREVOZCHIKI Тут мы получили суммарную долю всех перевозчиков в %%. 4. Теперь вычисляем сколько нам надо записей на 1%. Это уже делаем в Delphi, хотя можно было сделать и за 1 шаг вместе с пп. 2 и 3, но тут есть специфичность от БД, так что не будем торопиться. Код:
var ItemsPerPercent : Integer; begin // Query1 - запрос из шага 2 // Query2 - запрос из шага 3 ItemsPerPercent := Round(Query1.Fields[0].AsInteger/Query2.Fields[0].AsInteger); If ItemPerPercent = 0 Then Inc(ItemPerPercent); Очередное замечание. If ItemPerPercent = 0 Then Inc(ItemPerPercent) - страховка от ошибки, когда на 1% приходится меньше 1 записи. В приципе, в таком случае кому-то недостанется чего везти, но это уже их пробема. 5. Теперь нам надо расставить перевозчиков. Собственно, надо взять каждого перевозчика и посчитать сколько записей приходится на его долю, а затем пройти по ведомостям нужное кол-во строк и поставить их в значение этого перевозчика. Тут нам потребуется 2 запроса и маленький код на Delphi. Запрос А. Получение перевозчиков. При этом сортируем их обратно пропорционально их доле (наиболее вероятно, что тебе все-таки хочется перевозчиков с большой долей удержать, загрузив их работой). Код:
SELECT PEREVOZCHIK, DOLYA FROM PEREVOZCHIKI ORDER BY DOLYA DESC Запрос Б. Получение неназначенных ведомостей. Кстати, их тоже можно как-нить отсортировать, но тут я не знаю от чего это может зависей. Запрос аналогичен запросу шага 2, но тут мы получаем список, а не одно число. Здесь нас интересует просто поле, где надо указать перевозчика, т.к. остальны ерасчеты мы уже сделали, ну и поле ID (надеюсь ты его не забыл) для идентификации записи. Код:
SELECT ID, PEREVOZCHIK FROM VEDOMOST WHERE RASSTOYANIE > 200 И теперь маленький кусочек на Delphi, который расставит перевозчиков. Сами значения будут устанавливаться с помощью запроса, т.к. мне прсто так удобнее. Код:
const UPD_QUERY = 'UPDATE VEDOMOST SET PEREVOZCHIK = ''%s'' WHERE ID = %d'; var N : Integer; C : Integer; begin // Query3 - запрос А // Query4 - запрос Б // Query5 - параметризованный запрос, которым мы и будем ставить значения. Query3.Open; Query4.Open; Query5.SQL.Clear; Query3.First; Query4.First; C := 0; N := Query3.FieldByName['DOLYA'].AsInteger * ItemsPerPercent; // Кол-во записей для перевозчика. While Not Query4.Eof Do Begin Query5.SQL.Clear; Query5.SQL.Add(Format('UPD_QUERY',[ Query3.FieldByName('PEREVOZCHIK'].AsString,Query4.FieldByName['ID'].AsInteger)); Query5.ExecSQL; Inc(C); If C > N Then Begin Query3.Next; N := Query3.FieldByName['DOLYA'].AsInteger * ItemsPerPercent; // Кол-во записей для перевозчика. C := 0; End; Query4.Next; End; Собственно, что делается. N - число записей в ведомостях, которые надо поставить для текущего перевозчика в соответсвии с его долей. С - текущий счетчик. Бежим по ведомостям и ставим туда текущего перевозчика. Если для текущего перевозчика мы посавили нужное кол-во ведомостей, то переходим с следующему, пересчитываем N и сбрасываем С. PS. Можно написать и короче. Для себя бы я сократил всю эту кашу на треть и сделал бы это скорее на сервере (принцип не отличается) в виде хранимой процедуры, а с клиента (из Дельфей) просто дергал бы эту процедуру и выводил результат. Но зато тут подробно рассмотрен алгоритм решения такой задачи. Последний раз редактировалось lmikle, 10.07.2008 в 21:35. |
#6
|
|||
|
|||
![]() Спасибо большое сегодня как проснусь сразу начну ковырять, уже неделю читаю все что попадается по базам
![]() |