|
Организация очередей?
|
|||
---|---|---|---|
#18+
Привет! Кто-нибуть сталкивался с такой задачей: надо организовать базу движения очередей клиентов. Пока пришла только одна идея: создать таблицу с порядковыми номерами в очередях (таких 10), связанную один-к-одному с таблицей клиентов (чтоб не блокировать таблицу клиентов). При вставке/удалении в середину очереди открывать транзакцию, блокировать всю таблицу очередей, обновлять все записи более какого-то номера на N+1, вписывать освободившийся номер клиенту, закрывать транзакцию. А может есть идеи поэлегантнее и, главное, понадежнее? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2004, 23:55 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
1. 10 очередей или 10 клиетов в очереди? 2. Обязательно ли клиенту знать его порядковый номер? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2004, 14:57 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 Accessor: 1) 10 очередей (но это в принципе-то не важно), по 5-2000 клиентов на каждую, причем могут быть одновременно (пересекатются) 2) Обычно хотят знать. Но это критично знать самой организации, т.к. "снимок" очереди на определенный момент оформляется как документ. Пока работа идет в Word+Excel с кучей заморочек... А база (на dBase) пока учитывает только самих клиентов. Надо все это слить в одну задачу в Access. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2004, 19:58 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Первое действительно не важно. А вот со вторым сложнее... А по какому признаку клиент заходит в очередь? Как определяется его место там? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2004, 20:09 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
AccessorА по какому признаку клиент заходит в очередь? Как определяется его место там? По решению оператора на основе разных факторов, в т.ч. даты первого обращения, имеющихся преференций и т.д. Свободу у оператора отбирать нельзя. Ему будет выводиться только подсказка. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2004, 23:36 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Тогда, думаю что то что вы предложили - лучше всего. Если я правильно понял: Таблица clientqueue ----------- queue_id - идентификатор очереди client_id - клиент num - порядковый номер клиента в очереди Добавление в клиента C очередь Q под номером N в 2 приема: UPDATE clientqueue SET num=num+1 WHERE client_id=C AND queue_id=Q AND num>=N INSERT INTO clientqueue VALUES (Q,C,N) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2004, 00:48 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
AccessorТогда, думаю что то что вы предложили - лучше всего. Если я правильно понял: Таблица clientqueue ----------- queue_id - идентификатор очереди client_id - клиент num - порядковый номер клиента в очереди Добавление в клиента C очередь Q под номером N в 2 приема: UPDATE clientqueue SET num=num+1 WHERE client_id=C AND queue_id=Q AND num>=N INSERT INTO clientqueue VALUES (Q,C,N) ИМХО в упдате убрать условие client_id=C и оставить только queue_id=Q AND num>=N ибо (client_id, queue_id) это ключ!!! ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2004, 09:02 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
paparome ИМХО в упдате убрать условие client_id=C и оставить только queue_id=Q AND num>=N ибо (client_id, queue_id) это ключ!!! Да, с client_id я ошибся. Извините. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2004, 09:09 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Работа с людми вещ тонкая наверняка будут разборки с операторами и клиентами на тему "вас тут не стояло" потому лучше оформлять не конкретное место в очереди, а добавлять клиента всегда в конец, а потом дополнительной проводкой(записью в таблицу) изменять его вес при сортировке обязательно сопровождая такое изменение служебной инфой кто , когда и пр. а сам вес вычислять по таблице проводок как Sum всех операций а порядковый номер в очереди на заданный учетный период будет получатся через нумерацию строк запроса (сумма с накоплением в отчете по полю =1) Минимальный набор операций 1)Добавить клиента в конец очереди 2)Удалить клиента из очереди 3)обогнать впереди стоящего 4)пропустить сзади стоящего все остальные действия можно представить ввиде последовательности элементарных операций из минимального набора ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2004, 09:24 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 Accessor Спасибо за потдержку идеи :) Только я для ускорения работы хотел завести на каждую очередь отдельное поле или табличку... 2 Latuk Разборки оператор-клиент конечно бывают. Но все в основном регулируется нормативными актами/правилами, так что особо не поспорят :) И вставка чаще всего идет как раз где-то в середину. Ваша идея конечно интересная, но: - и как определять вес? Каждый раз поднимать всю исорию для Sum? - это чтобы вставить в начало очереди надо прогнать в цикле клиента через 2000 записей по-одному? Ни чего себе транзакция получится... При моем решении, хотя оно и "в лоб", можно обогнать/пропустить сразу 2000 клиентов. - сортировать по номерам нормально можно только в отчете. В форме (карточке) клиента номер нормально не получить. - надежность получается низкой, т.к. нет однозначного соответствия. - тормоза обеспечены однозначно. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2004, 21:29 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
AbelТолько я для ускорения работы хотел завести на каждую очередь отдельное поле или табличку... Думаю что это нецелесообразно... От 20000 записей в таблице еще никто не умирал, а выгода налицо - не надо мучаться с 10-ю таблицами. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2004, 22:40 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Появилась связанная проблемка :( Если отследить сбой расчетов при появлении одинаковых номеров легко обычным GROUP BY, то как же отлавливать возможные "дырки" в последовательности? Гнать FOR...NEXT не хочется :( ... |
|||
:
Нравится:
Не нравится:
|
|||
07.12.2004, 00:31 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Особойо проблемы я не вижу. Все делается посредством пары-тройки запросов. Например: добавление в очередь в определенную позицию (номер по порядку): Код: plaintext 1. 2. 3. 4.
Дальше по аналогии... ... |
|||
:
Нравится:
Не нравится:
|
|||
07.12.2004, 01:09 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Я описаль лиш элементарные логические операции совсем не обязательно ими ограничиватся или физически организовывать их в лоб например по моему способу для вставки клиента в середину очереди достаточно добавить в таблицу проводок всего одну запись в ваше придется проадейтить всех кто ниже его. так же мой способ позволит определить место в очереди на любое время и легко строить разного рода отчеты например динамику продвижения в очереди и т.п. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.12.2004, 08:27 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
LatukЯ описаль лиш элементарные логические операции совсем не обязательно ими ограничиватся или физически организовывать их в лоб например по моему способу для вставки клиента в середину очереди достаточно добавить в таблицу проводок всего одну запись в ваше придется проадейтить всех кто ниже его. так же мой способ позволит определить место в очереди на любое время и легко строить разного рода отчеты например динамику продвижения в очереди и т.п. Я не говорю, что твой вариант плох, я просто предложил свой. Да и в апдэйте 2000 записей я не вижу никакой заморочки. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.12.2004, 09:16 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Все извините что отвечаю вечером: на работе интернет отрубили 2 Vsevolod_V Как раз этот подход сначала и обсуждался. Минусы: - невозможно отследить историю очереди в целом (разве что делать иногда "слепок"); - надо при старте проверять на сбой расчетов (дубли номеров и дырки [последнее не совсем ясно]); - надо блокировать всю таблицу для update (но если очереди в разных табличках, то блокируется только одна); - необходимость явной транзакции (т.к. в 2 шага). Плюсы: - скорость работы; - однозначность интерпретации данных (клиент = N очереди), которые можно показать и в форме, и в отчете, и искать по нему! - независимость очереди от сбоя системных часов и ошибки ввода даты на машине оператора. 2 Latuk Ваш подход сложноват для практики, но интересен. Номер очереди получается расчетным и это теоретический плюс для БД. Но идея механизма проводок не совсем понятна. Ясно, что это id клиента, id очереди, время проводки и некий параметр изменения веса. Что это может быть? А если такой "вес" уже есть в базе? 2 All Неужели никто на практике не сталкивался с подобной задачей? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.12.2004, 00:41 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Для того чтобы уменьшить количесво обновлений в тразакции, можно делать не сплошную нумерацию, а с шагом скажем M. если клиент должен встать между номерами в очереди k1 и k2 - давать номер (k1+k2)/2 если k2>k1+1 ;в противном случае всем, тем имеет номер >=k2 добавить к номеру M и вернуться к предыдущему шагу Естественно, всё делать в одной транзакции ... |
|||
:
Нравится:
Не нравится:
|
|||
08.12.2004, 00:59 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 Alexey Sh Хорошая идея! ;) А порядковый номер, если не в отчете, тогда рассчитывать как Count(*) Where номер<=k. И чтобы реже двигать всех, сделать шаг M=1000. Собствернно говоря получился аналог "веса клиента", предложенный Latuk'ом ... |
|||
:
Нравится:
Не нравится:
|
|||
08.12.2004, 22:58 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Abel2 Alexey Sh Хорошая идея! ;) А порядковый номер, если не в отчете, тогда рассчитывать как Count(*) Where номер<=k. И чтобы реже двигать всех, сделать шаг M=1000. Собствернно говоря получился аналог "веса клиента", предложенный Latuk'ом И не забыть добавить процедуру периодического переупорядочивания ... |
|||
:
Нравится:
Не нравится:
|
|||
09.12.2004, 10:50 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Идея Латука интересна, но кажется не вполне прозрачна: Положим: 1)таблица клиентов. 2)Таблица очередей (не апдейтится). 3) Таблица "проводок" (сдвигов, с полями дат проводок). Для простоты возьмем 1 очередь. пример вырождается в таблицу клиентов (ik) с полем номере очереди N0, и таблицу шифтов с полями даты, клиента и величины сдвига (шифта shift). В 0 приближении новый номер клиента IK на дату DATE будет считаться как N=N0(IK) + Sum(shift(IK, date<DATE)) + f(ik<>IK) где физ смысл f(ik<>IK) - это сдвиг в очереди клиента IK из-за сдвигов других клиентов (ik<>IK). Если не учитывать этого момента, то будут совпадения в величинах N0(IK) + Sum(shift(IK, date<DATE)) для разных IK. Видит ли латук, как в SQL правильно посчитать шифт элемента из за сдвигов других? если я предположу, что от порядка шифтов на некий момент времени результат не изменится, я, кажется, могу записать: f ~ COUNT(ik, WHERE N0(ik)<N0(IK) AND (N0(ik)+ Sum(shift(ik<>IK,date<DATE))>N0(IK)) - COUNT(ik, WHERE N0(ik)>N0(IK) AND (N0(ik)+ Sum(shift(ik<>IK,date<DATE))<N0(IK)) - а это вполне переводится на SQL, правда скорость его будет похоже расти как произведение числа клиентов на полное число проводок в очереди. (и, честно сказать, я не до конца уверен в логичности перехода от перестановочности шифтов к приведенной записи функции сдвига номера текущего клиента сдвигами других). С другой стороны, если в таблице проводок все же при атомарной операции записывать не величину изменения "сдвига" для одного клиента, но величины всех сдвигов (тем не менее сохранив дату операции - для истории), то при увеличении числа записей в >~2 раза <~NO раз (2 - для перестановок только последовательных, а NO (где - NO длина очереди) - для перестановок из начала в конец очереди), мы сможем считать номер как N=N0(IK) + Sum(shift(IK, date<DATE)) (т.к. сдвиг других элементов уже учтен в параллельных проводках сдвига других клиентов той же операцией), и сэкономить на посчете внутренних сумм в вычислении сдвига другими клиентами. При этом: 1. все записи проводок только добавляются, блокировки (если есть позаписная) одним процессом другого быть не должно 2. таблицу "проводок" разумно разбить на 2 а)- "шапка" - таблица операций с полем даты и расшифровкой операции, б) - атомарные проводки-шифты элементов (согласованные проводки можно делать как в триггере, так и в приложении, в одной транзакции). ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2004, 11:28 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 4321 Мдя... теперь ясно, что вариант Латука замечателен для Oracle, но убийствен для mdb :( Кстати, что Вы подразумеваете под триггерами в mdb :) Не могли бы прокомментировать следующие моменты: - Что Вы имеете в виду под "должен быть один процесс"? Ведь транзакция и так выступает как 1 процесс? - Отделять "шапку" в другую таблицу это для скорости? Или подразумевается 1 ко многим? - Чтобы изменить кого-то в середине очереди, надо одномоментно каждый раз добавлять по 1000 проводок? Если так, то у меня mdb, а не Oracle :( ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2004, 23:43 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
З.Ы. Кстати, а смысл добавлять кучу шифтов, когда можно добавить на текущую дату просто пересчитанные номера очереди. И никаких count, sum etc. Просто "=" и усе!!! И история хранится, и устаревшую историю можно скидывать периодически в архив. Гениально. Вот что значит симбиоз идей ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2004, 23:55 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
AbelЗ.Ы. Кстати, а смысл добавлять кучу шифтов, когда можно добавить на текущую дату просто пересчитанные номера очереди. И никаких count, sum etc. Просто "=" и усе!!! И история хранится, и устаревшую историю можно скидывать периодически в архив. Гениально. Вот что значит симбиоз идей Согласен. Более того, "проводки" при помощи одиночных записей "шифтов" плохи тем, что на самом деле высказанная выше гипотеза перестановочности сдвигов не имеет никаих прав на существование. (Что демонстрируется при помощи двух "сдвигов": - 2-го элемента через один и третьего через один - а именно, в зависимости от порядка мы будем в результате иметь либо 1-2-3-4 (если сначала сдвинуть второй, потом тертий) или 1-4-2-3 - если сначала сдвигать третий, потом второй)) Т.е. при помощи обычных групповых операций SQL итогового положения по истории "нессимметричной" записи проводок (только для одного элемента, а не всех согласованных сдвигов номеров очереди) не восстановить - нужно еще и учитывать порядок "проводок" - процедура становится существенно рекурсивной. Посему придется записывать все произошедшие сдвиги (именно это выше и предлагалось - "шапка" - идентификатор и аналитика операций, сдвиги - величины смещений нумерации всех сдвинутых операцией элементов). Что эквивалентно записи "снимка" очереди (достаточно перезаписать не всю очередь, а только сместившиеся при сдвиге элементы - записей в таблице истории будет существенно меньше, но с выборкой придется исхитрятся - на вскидку не так уж сложно - для каждого клиента надо выбирать последнюю по времени, не превосходящему момент выборки, запись в очереди, "моментальный снимок" будет запросом наподобие: SELECT ik, (SELECT TOP 1 nk From очередь WHERE очередь.ik = клиенты.ik AND очередь.Дата<=[Дата выборки] AND очередь.id=[очередь выборки] ORDER by очередь.Дата DESC) AS nk FROM клиенты) - тут надо смотреть, что вы предпочитаете оптимизировать, быстродействие на выбоку или объем и быстродействие на запись. Вероятный плюс записей полного снимка очереди: - можно наложить констрайнт типа уникального индекса (id,ДАТА,ik,nk), который будет гарантировать логическую непротиворечивость снимков как целое. При записи в историю только сместившихся в очереди клиентов такой контроль логической непротиворечивости за счет констрайнтов в мдб точно не возможен (придется в вба проверzть отсутствие совпадений nk в вышеприведенной выборке), а на SQL-сервере скорей всего потребует аналогичного (вба) триггера (на стейтмент, а не на запись) проверки непротиворечивости. ЗЫ. под триггерами в мдб я ничего не подразумеваю. я подразумеваю, что ваш мдб(адп,мде) может быть клиентом чего угодно, в т.ч. некоего "нечта", поддерживающего такие небезызвестные механизмы "обработки событий" данных, как тригеры на стейтмент. Если это так - уместнее использовать триггеры, чем ненадежный (не перекрывающий все возможные способы изменения данных) механизм обработки событий форм клиента. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.12.2004, 13:21 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
4321 При записи в историю только сместившихся в очереди клиентов такой контроль логической непротиворечивости за счет констрайнтов в мдб точно не возможен Ну почему же? Если завести поле "дата_устаревания", то должна соблюдаться уникальность всех записей по (id, ik, Nk, время_добавления, время_устаревания). Во всех новых записях время_устаревания = null или 0. ЗЫ. Нет, у меня .mdb будет как собственно база. Есть и Oracle, который я только админю, но писать для него приложения не собираюсь. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.12.2004, 16:46 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
... правда тогда нужен update и теряется вся прелесть метода :( Итак, подведем итог: выявилось 2 перспективных подхода, которые надо будет обкатать на практике. 1) от Alexey_Sh 2) от 4321. Всем спасибо. Если будут еще идеи, пишите :) ... |
|||
:
Нравится:
Не нравится:
|
|||
11.12.2004, 21:03 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Возможно этот пример очереди поможет решить задачу: Const WANT_FREE_PERCENT = .1 ' 10% свободного пространства. Const MIN_FREE = 10 ' Минимум свободных ячеек. Global Queue() As String ' Массив очереди. Global QueueMax As Integer ' Наибольший индекс массива. Global QueueFront As Integer ' Начало очереди. Global QueueBack As Integer ' Конец очереди. Global ResizeWhen As Integer ' Когда увеличить размер массива. ' При инициализации программа должна установить QueueMax = -1 ' показывая, что под массив еще не выделена память. Sub EnterQueue(value As String) If QueueBack > QueueMax Then ResizeQueue Queue(QueueBack) = value QueueBack = QueueBack + 1 End Sub Sub LeaveQueue(value As String) value = Queue(QueueFront) QueueFront = QueueFront + 1 If QueueFront > ResizeWhen Then ResizeOueue End Sub Sub ResizeQueue() Dim want_free As Integer Dim i As Integer ' Переместить записи в начало массива. For i = QueueFront To QueueBack - 1 Queue(i - QueueFront) = Queue(i) Next i QueueBack = QueueBack - QueuePront QueueFront = 0 ' Изменить размер массива. want_free = WANT_FREE_PERCENT * (QueueBack - QueueFront) If want_free < MIN_FREE Then want_free = MIN_FREE Max = QueueBack + want_free - 1 ReDim Preserve Queue(0 To Max) ' Если QueueFront > ResizeWhen, изменить размер массива. ResizeWhen = want_free End Sub ... |
|||
:
Нравится:
Не нравится:
|
|||
11.12.2004, 22:27 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Abel... правда тогда нужен update и теряется вся прелесть метода :( Итак, подведем итог: выявилось 2 перспективных подхода, которые надо будет обкатать на практике. 1) от Alexey_Sh 2) от 4321. Всем спасибо. Если будут еще идеи, пишите :) Ну есть еще стандартная метода организации списков в программмировании - указатель на предыдущий (или предыдущий и последующий) элемент. (при перестановке меняются указатели только потревоженных элементов очереди). Метод хорош тем, что всегда (в запись) вовлечены только элементы, меняющие своих впредиидущих. (можно вести и как историю - нет проблем). "Плох" тем, что очередь строится рекурсивно (а не наперед ограниченным количеством SQL запросов). Но, если учесть, что в ваших руках VBA -нет проблем скрестить этот экономичный к данным (и к их изменению) способ хранения списка с SQL - просто пишете свою функцию-указатель на предка(потомка) и (ее же, но с другим параметром) - ф-ию расчета порядкового номера, пара индексов сделает это еще и быстрым. +Чтобы инициировать набор данных для ф-ии 1 раз - вызов с третьим параметром инициирует/очищает статик переменную. После этого все выборки строятся легко и непринужденно в SQL. еще способ - почитать как устроены индексы (структуры их размещения), и попытаться реализовать их аналог. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.12.2004, 23:34 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 4321 Здорово, но трудоемко. И что-то я сомневаюсь в быстродействии... Но оставим как вариант :) А это: 4321почитать как устроены индексы (структуры их размещения), и попытаться реализовать их аналог. уж чересчур. Еще мне не хватало b-деревья ручками делать :) Сегодня получил новую вводную для ТЗ. Применительно к БД очередь согласились видеть как составленную из кодов дат как параметра сортировки (типа "19991203"), и только в случае совпадения кодов, место может выбирать оператор, причем, видимо, обычно в конец группы... Попробую применить предложенные в топике методы к новым условиям. Возможно, так задача упростится. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2004, 21:17 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
ЗЫ 2 4321 Фуннция расчета цепочки это либо цикл в лоб по указателям, либо рекурсивная функция? Это значит при сортировке для расчета каждой позиции гонять цикл по всей таблице... Не, лучше я Вашим предыдущим предложением воспользуюсь :) А про цепочки-то я знаю 8) 2 Amel_old ваше предложение для безостановочно работающего и не зависающего компьютера... ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2004, 00:26 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
AbelЗЫ 2 4321 Фуннция расчета цепочки это либо цикл в лоб по указателям, либо рекурсивная функция? Это значит при сортировке для расчета каждой позиции гонять цикл по всей таблице... Вариантов больше 2х. Например однократное заполнение расчетного статик массива или коллекции (в зависимости от доминирующего типа предполагаемых вызовов) (если объем данных не шибко велик) при первом вызове (если массив пуст - его заполняем, нет - возвращаем значение) и возврат уже посчитанных значений при каждом последующем. В этом случае цикл "гоняется" для первой (попавшейся) позиции, и не гоняется для всех последующих. Только во все запросы надо не забывать вписывать в WHERE стартовый вызов ф-ии, переопределяющий статик переменные (в т.ч. обнуляющий массив/коллекцию - а то вдруг данные поменялись между 2-мя запросами). Для заведомо небольшой очереди допустимо, но нужно ли? Кстати, вероятно возможен выигрыш по скорости за счет снижение затрат на чтение из больших таблиц с "полными" очередями. Если нормально заоптимизировать вызовы/расчеты. И если результаты расчетов влезут в оперативку, а не полезут в своп. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2004, 11:33 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 4321 Спасибо за столь активное обсуждение темы и хорошие идеи!!! В вашем варианте можно и ограничение уникальности накладывать... Сколько массив займет в оперативке? Например, 20000 записей * (4 байта ключа + 4 байта рассчетного номера) = 160 Kb. Всего-то? А историю всей очереди хранть не получится: указатели ведь должны быть однозначными. С другой стороны, а так ли она необходима?... То что вызывать функцию в каждом запросе это понятно. Но ведь пока даже один цикл считается, ДРУГОЙ пользователь изменяет очередь и у клиента может получится 2 разных номера. Исходя из новых вводных, есть идея хранить таблицу в виде: (id_клиента, код_сортировки, подкод_по_порядку, дата_вставки, дата_отмены) Любое изменение: INSERT новой записи и UPDATE одной отмененной. Можно делать выборки по дате и блокируется при изменении всего 2 записи. Расчет номера по Count(*) WHERE [код] + [подкод] <= (N + M) Правда это только если вставка будет всегда в конец группы по коду. Надо уточнить. ЗЫ. У некоторых юзеров и сама винда в свопе сидит (RAM=32) :( ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 00:51 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Abel2 4321 А историю всей очереди хранть не получится: указатели ведь должны быть однозначными. С другой стороны, а так ли она необходима?... историю хранить таки можно. Указатель однозначен на дату. Уникальность сама по себе и без истории не обеспечивает логической непротиворечивости - отсутсвие закольцовок надо проверять. Abel То что вызывать функцию в каждом запросе это понятно. Но ведь пока даже один цикл считается, ДРУГОЙ пользователь изменяет очередь и у клиента может получится 2 разных номера. В вызове из запроса у вас заполняется статик массив - никакие изменения в исходном наборе на него уже не подействуют. В самом процессе расчета массива тоже можно либо брать снапшот (но тогда не доступны, кажется, индексы - придется ходить Find-ом, а не Seek -ом, что медленно), либо объявлять транзакцию (надо смотреть, не скажу влет что будет в транзакции с рекордсетом, который dbOpenTable при сторонних изменениях). Abel есть идея хранить таблицу в виде: (id_клиента, код_сортировки, подкод_по_порядку, дата_вставки, дата_отмены) Любое изменение: INSERT новой записи и UPDATE одной отмененной. Можно делать выборки по дате и блокируется при изменении всего 2 записи. Расчет номера по Count(*) WHERE [код] + [подкод] <= (N + M) Правда это только если вставка будет всегда в конец группы по коду. Надо уточнить. не въехал есть стандартная метода хранить дерево как "указатели" (некие расчетные величины на обходе дерева) на правый и левый элементы по обходу. (см поиском в сетке, есть. кажется и на сайте в статьях). При этом никакой рекурсии - все что требуется считается групповыми запросами. Вот только пересчет указателей при вставке в середину затрагивает почти полдерева. Но, поскольку мы хотим хранить историю - никаких апдейтов (разве кроме правки самой истории) не нужно - нужно просто записать новое дерево после любой перестановки узлов. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 11:21 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
авторВот только пересчет указателей при вставке в середину затрагивает почти полдерева только пересчет номеров .(!) (поэтому его иногда ведут динамически) к-во затрагиваемых указателей (записей) при вставке всегда не больше 3х. (предыдущая, следующая и вставленная) A<-B<-C A<-D<-B<-C При перестановке добавляется еще 2. Итого максимум 5 ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 11:42 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
как было нарисовано - одностороняя ссылка - на 1 меньше ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 11:45 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Мшсещырф авторВот только пересчет указателей при вставке в середину затрагивает почти полдерева только пересчет номеров .(!) (поэтому его иногда ведут динамически) к-во затрагиваемых указателей (записей) при вставке всегда не больше 3х. (предыдущая, следующая и вставленная) A<-B<-C A<-D<-B<-C При перестановке добавляется еще 2. Итого максимум 5 см в тексте: [quot]...как "указатели" (некие расчетные величины на обходе дерева) на правый и левый элементы по обходу[\quot] - вах, ми в этам смисле "указателей" - именно как номеров по обходу - они меняются для всего дерева далее по обходу от места вставки. если именно указатели на запись - то энто то, что абсуждалось више. И там действительно все как в списках. Но к лобовому SQL не шипка пригодно (рекурсия, однако). Тут все так, как Мшсещырф рассказывает. ЗЫ кстати обход очереди, в силу отсутствия ветвей, вырождается просто в её нумерацию. (т.ч. будет не отличимо от хранения снимков очередей). ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 11:53 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
авторНо к лобовому SQL не шипка пригодно (рекурсия, однако). Только в случае, если кому-то нужны НОМЕРА. Интересно, а кому они нужны? стоящему в очереди знать надо в лучшем случае только за кем он стоит. Ну на самый край - кто за ним. Это позволит задать вопрос конкретному экземпляру - Вы крайний? И он сможет ответить - да или нет. Обслуживающему очередь нужно только умение определить пуста очередь или нет и сказать - "следующий". Менеджеру, управляющему очередями, возможно потребуется умение ответить на вопрос - какой длины данная очередь. Вот без номеров - кому жить нельзя? :)) ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 12:01 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 Мщсещырф В том то и прикол, что стоящий в очереди НЕ должен знать кто перед ним и за ним. Только номер. Да ладно с ним, а вот МЕНЕДЖЕР должен создавать "список очереди" (финансовый документ!!!) и иметь возможность вставлять в середину. Вообщем см. постановку задачи в первых постах. 2 4321 а) Ну вот, благополучно вернулись к предыдущему варианту :) б) Я имел ввиду что уникальность без даты и истории, если update'ть указатели. Колец не будет. Если же только insert'ить, то тогда конечно Вы правы. в) Почему же "не въехал"??? Я имел ввиду не дерево, а новые условия задачи (см. пост от 14.12.04 21:17). В распоряжение попал почти естественный ключ (код даты), и только при одинаковой дате (бывает у 2-4 записей) прибавлять "доп. ключ". Сортировка становится элементарной. Но есть пока неясности в ТЗ по этому вопросу. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.12.2004, 22:20 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
"постановка задачи" в первых постах мне абсолютно не понятна, как и язык, на котором она обсуждалась. Подключился, когда показалось, что буквы во что-то опознаваемое (мною) складываются. Видимо ошибся. Вот прочитал во всех дрступных направлениях: автора вот МЕНЕДЖЕР должен создавать "список очереди" (финансовый документ!!!) и иметь возможность вставлять в середину. Никак у мене не склеивается крустальная ваза: Ежели "список очереди" - это финансовый документ, то что ему можно вставить в середину? (буде найдутся гусары - попрошу молчать...) PS1 номер так номер - нет проблем - подошел к очереди, взял из ящика номер. стоишь с ним. вдоль номера бегает менеджер, переставляет, собирает и раздает номера. Главное не забыть сдать номер попадя на обслуживание. Вошел в обслуживание, сдал номер ( к моменту входа он первым будет) стоящий за тобой цапнул этот номер сам, или с помощью "менеджера", выбросив/отдав свой. Таким образом элемент, попавший в очередь, будет обладателем всех номеров с номера равного длине очереди до 1 при обслуживании без приоритетов/перестановок. Иначе возможны пропуски в последовательности номеров для элемента. Таким образом, номер для элемента есть функция времени (момента наблюдения) и в отрыве от составленного на конкретный момент "финансового документа" не является характеристикой ни очереди, ни элемента находящегося в ней. При проведении перестановки элементов количество затрагиваемых апдейтом записей в среднем равно половине длине средней очереди :)) ЗЫ2 а может Вам это показалось, что Вы имеете дело с очередью? Может какое другое название удачней будет? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.12.2004, 00:01 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
пардон - средняя "длина" апдейта чуть больше четверти средней длины очереди при перенумеровке пролучится... (с выражением лица) ... |
|||
:
Нравится:
Не нравится:
|
|||
17.12.2004, 00:48 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Abel 2 Мщсещырф В том то и прикол, что стоящий в очереди НЕ должен знать кто перед ним и за ним. Только номер. Да ладно с ним, а вот МЕНЕДЖЕР должен создавать "список очереди" (финансовый документ!!!) и иметь возможность вставлять в середину. не принципиально для организации данных (в смысле реализуется интерфейсом, а не схемой данных) Abel Вообщем см. постановку задачи в первых постах. кроме того, что это должен ыбть перестраиваемый список я ничего содержательного в постановке не видел. (иметь возможность видеть историю, разве что - как опция) Abel 2 4321 а) Ну вот, благополучно вернулись к предыдущему варианту :) http://www.sql.ru/search/search.asp?wci=rcdoc&url=http%3A%2F%2Fwww%2Esql%2Eru%2Farticles%2Fmssql%2F01091502TreesInSQL%2Eshtml&ex=1&pool_size=10&is=exsqlru&context=Joe+Celko&contextcond=phrase&body=1&orderby=%24rel&doc_per_page=10&output=full - можно, кажется, рассматривать как перенос идеи сквозной нумерации со списков на деревья (в силу неопределенной наперед топологии дерева требуется 2 номера "правый" и "левый" для ее восстановления по "нумерации") Abel б) Я имел ввиду что уникальность без даты и истории, если update'ть указатели. Колец не будет. Если же только insert'ить, то тогда конечно Вы правы. Почему не будет колец? (Пристроим 5 за 10 (проапдейтим его ссылку, + пусть 11-го для простоты еще нет), а ссылку 6-го оставим на месте - схема данных позволит -> "снятие" проблемы только через запрещение несогласованных изменений (триггер в серверном случае, запрет обхода некой процедуры перемещения узлов - в случае клиентсого контроля) Abel в) Почему же "не въехал"??? Я имел ввиду не дерево, а новые условия задачи (см. пост от 14.12.04 21:17). В распоряжение попал почти естественный ключ (код даты), и только при одинаковой дате (бывает у 2-4 записей) прибавлять "доп. ключ". Сортировка становится элементарной. Но есть пока неясности в ТЗ по этому вопросу. пост от 14.12.04 21:17 не читабелен (не понятоблян). Если я пральна догадываюсь, очередь завсегда в порядке дат "постановки на учет" (перестановка в начало осуществляется заменой даты на фиктивную), Тогда уж не надо приводить даты к тексту - оставьте полную дату, а "всовывание" в очередь внутри даты осуществляйте за счет ее дробной части (часов, минут, секунд и т.п.) - там много влезет (можно прикинуть - по величине дискрета двоичного представления) , и отпадет надобность в поле внутридатой (внутридатской) сортировки. Только вот (сплошная) нумерация у вас "по любому" рекурсивна - в отличии от хранения номеров "битой цифрой" вы не гарантируете сплошности и постоянства приращения "меры" вдоль очереди. Провести сопоставление с натуральным рядом множества с такой "мерой" можно только по результатам проведения процедуры "натурального" упорядочивания (ORDER By [мера]->recorset->absolutposition->Number), что автоматом правда делается (только) в отчетах. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.12.2004, 11:45 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
2 4321 Типа не понял: зачем это 4321 (ORDER By [мера]->recorset->absolutposition->Number) В отчете достаточно ORDER BY + нумерация с накоплением по +1, а для получения отдельного номера почему не подойдет count(*) WHERE date <= datQueue ? Текстовое представление даты заведено до меня (им считают в Word-e ) А хранить секунды это прикольно :) 4321Почему не будет колец? (Пристроим 5 за 10 (проапдейтим его ссылку, + пусть 11-го для простоты еще нет), а ссылку 6-го оставим на месте 11 как раз должен быть. Он будет называться EOF, а самый первый BOF. Вставка только между ними. Две сцилки на элемент "5" нарушат уникальность. И поле сцилок должно быть not null. 4321 не принципиально для организации данных Согласен. Я просто пояснил, зачем нужны порядковые номера. 4321 кроме того, что это должен ыбть перестраиваемый список Об этом и речь 2 Victosha Victosha а может Вам это показалось, что Вы имеете дело с очередью? В документах называется просто "список". Но его движение сродни очереди, в которую приходят (условно "а мы сдесь занимали") и уходят из середины, в дополнение к пошаговому продвижению всех вперед по мере выбывания первых (как обычная очередь). Victosha Ежели "список очереди" - это финансовый документ, то что ему можно вставить в середину? Это "не принципиально для организации данных". Просто документ составляется на конкретный момент, утверждается руководством и используется в финансовых проводках (единомоментно - пакетом). До следующего раза очередь двигается вперед, в нее приходят новые и уходят некоторые старые элементы из середины (условно: клиент перебазировался в другой регион не дождавшись очереди. Но в очереди другого региона (это уже не моя задача) он встанет не в конец, а по той дате, как стоял у нас плюс-минус неск. номеров из-за преференций). Очередь исчисляется несколькими годами. А некоторые "дойдя до обслуживания" пропускают стоящих сзади, т.к. их на этот раз что-то не устраивает. "Снимок" состояния очереди после всех движений выливается в новый документ. И т.д. Потом звонит по телефону представитель клиента и интересуется своим номером. Надеюсь, так более понятно? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2004, 01:04 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Abel 2 4321 Типа не понял: зачем это 4321 (ORDER By [мера]->recorset->absolutposition->Number) В отчете достаточно ORDER BY + нумерация с накоплением по +1, а для получения отдельного номера почему не подойдет count(*) WHERE date <= datQueue ? это просто прорисовка внутреннего механизма получения номера, что оно само делается в отчетах я сказал. ИСпользование для нумерации вложенного запроса с count(*) WHERE date <= datQueue внутри некой большой выборки просто на порядок медленнее однократной загрузки рекордсета с возвратом из него всего необходимого обычным seek. Abel 4321Почему не будет колец? 11 как раз должен быть. Он будет называться EOF, а самый первый BOF. Вставка только между ними. Две сцилки на элемент "5" нарушат уникальность. И поле сцилок должно быть not null. ну вот вы и тор... начинаете изобретать механизм. Если not null + уникум -на чито ссылаются ваши искусственные EOF и BOF? (2 ссылки возникают, если только не закольцевать BOF на EOF - вы так и собирались?). Но тогда как удалить из кольца (с сылочной целостностью, надо полагать) хоть что-то? перед удалением придется перецепить ссылку у потомка (из за целостности) -> возникнут осложнение с уникальностью ссылок, а в NULL вы ее установить запретили. При этом если есть элементы за пределами EOF и BOF ("служебные") - они обязаны быть замкнуты в кольцо (в простейшем случае - сами на себя) - по тем же причинам уникальной не нулевой ссылки. Если попытаетсь пожертвовать ссылочной целостностью (вторичным ключем по pid) то это и того хуже - кто проверит целостноть в очереди? (т.е. наличие ссылаемого у ссылающегося) (можно правда так: .Requerd = False, и на _уровне таблицы_ правило типа NOT (pid IS NULL AND (id <> [eof] or id <> [bof]....) (вставлять в свойство таблицы, а не поля) где [eof] и [bof] (...) - константы, равные значениям id в BOF и EOF (и иных служебных). В итоге должно таки получится и средствами аксессовских правил. и без искуственного кольца. Если ввести [fof] - служебный элемент тоже с Null ссылкой в pid за пределами ([bof],[eof]), то ссылки следующего за удаляемым можно будет временно переключать по 1-й перед удалением....... но нужен ли вам весь этот гемор? (или вы надеетесь, что внутри транзакции проверки целостности не производятся? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2004, 12:35 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
4321 ИСпользование для нумерации вложенного запроса с count(*)... Я понял. Просто мы о разном говорили. Я не про вложенный, а про одиночный запрос (например, для ответа на телефонный звонок) 4321 на чито ссылаются ваши искусственные EOF и BOF? Предполагал, что BOF только на себя. Но "большое кольцо" тоже понравилось :) А другие служебные элементы не нужны. 4321 как удалить из кольца... хоть что-то? перед удалением придется перецепить ссылку у потомка (из за целостности) ... а в NULL вы ее установить запретили. А разве нельзя его временно сослать самого на себя? Возникнет этакий временный "служебный элемент". Но без not null может возникнуть разрыв цепочки ссылок. Историю можно хранить дискретно снимками, на моменты печати документа типа "список" :) Блин, а цепочки-то для каждого снимка должны быть свои... Нужен еще один параметр уникальности - код или дата. 4321 но нужен ли вам весь этот гемор? Не, гемор совсем не нужен Поэтому и ищу самую перспективную модель очереди. План тестового внедрения системы = 1-й квартал 2005. Есть пока время подумать З.Ы. Оказывается, в сутках аж 86 400 секунд!!! Да мне за уши хватит ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2004, 23:48 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
авторА разве нельзя его временно сослать самого на себя? а как же следующий (и уникальность?) То же и с самоссылкой БОФ (1-й последователь запрещает самоссылку - из за уникума) ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2004, 21:20 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
Согласен. А идея с самоссылкой боф появилаь еще до not null :) Кстати, контроль ссылочной целостности вроде можно отключить? При not null и уникальности возниклновение "висячей" ссылки маловероятно. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2004, 02:09 |
|
Организация очередей?
|
|||
---|---|---|---|
#18+
AbelСогласен. А идея с самоссылкой боф появилаь еще до not null :) Кстати, контроль ссылочной целостности вроде можно отключить? При not null и уникальности возниклновение "висячей" ссылки маловероятно. ??? мдя-с... ладно, не поленюсь: вставляем А, наследуем от него Б, удаляем А. - "маловероято"???? . При "списках" не отвертитесь от проверки отсутствия паразитных колец. Что легко понять: 1. уникум - обеспечивает только отсутствие ветвлений. 2. (целостность + нот нулл) - и только напару - обеспечивает отсутствие разрывов (данные организованы в множество колец, самое малое - из 1 элемента - самоссылка). Но не отсутствие "паразитных" колечек. 3. Отсутствие колец в вашем случае - это наличие вашего еоф/боф в каждом кольце (т.е. в каждой очереди - если очередей много, то и еоф/боф-оф - много) - как это сформулировать на языке ограничений аксесс - фих знает. 4. Вводя служебный элемент, для которго нот нулл не требуется (рибосому, или "менеджера очереди") - за счет механизма задания ограничения на уровне таблицы (описанном выше), а не поля - вы можете перекраивать очереди (кольца) не снимая ограничений с таблицы. Но от обязанности запретить возможность паразитных колец это вас не освободит. Делать это придется в вба (думается). ЗЫ: организация очереди присвоением уникального значения из упорядоченного множества (даты-времени, номера, или же некоего дабл значения) снимает проблему возможности возникновения колец (в списках по указателям). Но бесконечная вставка в один интервал потребует рано или поздно сдвига следующих элементов (из за кончности дискрета двоичного представления). ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2004, 11:56 |
|
|
start [/forum/topic.php?all=1&fid=45&tid=1669658]: |
0ms |
get settings: |
9ms |
get forum list: |
11ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
62ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
70ms |
get tp. blocked users: |
1ms |
others: | 278ms |
total: | 452ms |
0 / 0 |