|
|
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Имеются две таблицы, ROADS (дороги) и секции (SECTIONS), связаны один ко многим, так что дорога состоит из некого числа участков: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Изначально пользователь вводит дорогу (ее имя) и затем множество участков из которых эта дорога состоит, при этом каждый участок характеризуется собственным ограничением скорости. Участки должны идти в неком порядке (соседние номера не обязательно должны отличаться на единицу, главное, чтобы они возрастали от начала к концу). Когда пользователь вводит их подряд, от начала дороги до ее конца, проблем нет, т.к. ID секций идут последовательно. Однако, позже пользователь может разбить один или более участков. Например, если у нас были участки с ID 1,2,3,4,5, и пользователь захотел разбить участок 3 на два более коротких фрагмента с различными ограничениями скорости движения. Понятно что если просто получить новый ID, для нового участка, он будет равен 6, и порядок следования секций будет нарушен. Вставить участок с ID 3.5 тоже нельзя, т.к. поле целочисленное. Можно, конечно, нумеровать участки с неким запасом, скажем, 100, 200, 300, 400, 500..., и в случае необходимости вставлять новые записи в зазор, например с ID 350, но может имеются какие-то более удачные решения? Эти идентификаторы используются пользователем и он не должен перенумеровать записи вручную при вставке. Есть идеи как сделать это оптимально? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2008, 07:59 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Я бы использовал отдельные поля для идентификации отрезков и для указания порядка их следования и пересчитывал второе из них при вставке/разбиении участков в пределах данной дороги. Пересчитывать можно либо сразу при вставке, либо вставлять промежуточное значение (например 350 между 300 и 400) и периодически пересчитывать, чтобы восстановить исходные интервалы нумерации (например, через 100). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2008, 10:14 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
miksoftЯ бы использовал отдельные поля для идентификации отрезков и для указания порядка их следования+1 Это стандартный подход. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2008, 11:25 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
А может быть здесь нужен граф? тут ведь дороги не что-то само по себе... они ведь пересекаются, разветвляются (узлы), а скоростные участки между "узлами" - вес ребра... ну и хранить... что-то типа Код: plaintext 1. 2. 3. 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2008, 21:47 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
КифирчикА может быть здесь нужен граф? тут ведь дороги не что-то само по себе... они ведь пересекаются, разветвляются (узлы), а скоростные участки между "узлами" - вес ребра... ну и хранить... что-то типа Код: plaintext 1. 2. 3. 4. А может сделать "стандартно" - добавить поле РarentID и уже по нему строить дерево. У "корня" будет ParentID = 0 (или NULL). Добавлю (к любым вариантам): надо будет действовать так же, как при вставке в середину связного списка: корректировать ссылки на следующий / предыдущий элементы как у вставляемого элемента, так и предшествующего ему и у следующего за ним. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.03.2008, 07:25 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Станислав С...кийА может сделать "стандартно" - добавить поле РarentID и уже по нему строить дерево. У "корня" будет ParentID = 0 (или NULL). м.. родитель... корень... это ведь "сеть", какой здесь корень? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.03.2008, 11:25 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Кифирчик , все дороги ведут в Рим. (с) Вот его-то и можно взять за корень. А идея с пропиской "предыдущего" и "последующего" - неплохой вариант... ---------- Cache for Windows (Intel) 2007.1 (Build 369) Fri Jun 15 2007 15:25:42 EDT Cache for Windows NT (Intel) 5.0.20 (Build 6305) Fri Sep 16 2005 11:54:10 EDT ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.03.2008, 11:46 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
krvsa Кифирчик , все дороги ведут в Рим. (с) Вот его-то и можно взять за корень. А идея с пропиской "предыдущего" и "последующего" - неплохой вариант... Предыдущий и последующий, это, конечно, вариант.... Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"? Я так подозреваю, что никак. Думаю, что нумеровать "с дырками" и, при необходимости, перенумеровывать - не самый плохой и трудоемкий вариант. Особенно, если не делать к этому порядковому номеру никаких привязок. Выполняют же балансировку индексов и ничего, все живы, никто не умирает. А "предыдущий/следующий" - это столько гимора... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2008, 11:51 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Николай1Предыдущий и последующий, это, конечно, вариант.... Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"? Я так подозреваю, что никак. Все мыслят в рамках своих БД и их возможностей... Как-то писал редактор программ и там использовал такой подход к "нумерации" строк программы - проблем не имел. Ведь программер, что работал с редактором, всегда видел строки от "начала" и до "конца" в правильной последовательности... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2008, 12:15 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Николай1 Предыдущий и последующий, это, конечно, вариант.... Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"? Я так подозреваю, что никак. Зря Вы так... Дерево по данным SQL-запроса строится в "нормальных" серверах БД (Oracle, вроде бы должна быть такая фича в M$ SQL Server) на "ура". Надо только прочитать документацию... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2008, 12:18 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Станислав С...кий надо будет действовать так же, как при вставке в середину связного списка: корректировать ссылки на следующий / предыдущий элементы как у вставляемого элемента, так и предшествующего ему и у следующего за ним. этто как расс необязаттельно достаточно вдвое меньше данных, зачем дублировать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2008, 12:39 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Лучше всего будет, как и всегда, найти натуральный порядок для сегментов, если есть где взять, например - расстояние в метрах от начала дороги. Если нету - оцените, как часто будут добавляться сегменты. Если редко - то тоже есть лучшее решение. Храните порядок в real, равномерно от 1 до N + 1 Вставлять лучше по много сразу. Если надо вставить одну, то даете ей OrderSK дробный, 0.5 - в начало, N+0.5 - в конец, K+0.5 - в середину Если надо вставить M записей после K, то равномерно распределяете дробные значения: new_order(M, K) = (K+1)/(М+1) + K и после вставки сразу же переупорядочивать: Код: plaintext 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.03.2008, 19:08 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Забыл сказать, почему это лучше, - это резко упрощает логику. 1. Например интервал в 100 целых можно поделить надвое только 6 раз. 2. Есть ограничение в 99 вставок за раз, хотя и неактуально, но всеже - придется о нем помнить. 3. Получаете порядковый номер "бесплатно". В случае запасного интервала порядок будет стоить дополнительного запроса. Есть все же ограничение, следует помнить о нем. если у вас уже есть примерно 10 миллионов сегментов, то можно вставить за раз еще только 10 миллионов сегментов, не больше - мантисса не позволит :) Если это для вас плохое ограничение, то используйте double :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.03.2008, 19:31 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
gpХраните порядок в real, равномерно от 1 до N + 1 Вариант ни чем не лучше нумерации интервалов с большим шагом и даже хуже, поскольку из-за ошибок округления и потери точности можно легко получить неожиданный результат. Короче нумеруйте интервалы целыми числами с большим шагом, чтобы зарезервировать место для дальнейших вставок, по мере надобности перенумеровывайте. Перенумеровывать скорее всего придётся не часто, если вообще придётся, а запросы к таким данным будут простые и эффективные. В зависимости от конкретной БД можно придумать более экзотические варианты, например на базе пользовательских типов. Но почти наверняка экзотика будет во всём проигрывать дедовским методам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.03.2008, 21:42 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Станислав С...кий Николай1 Предыдущий и последующий, это, конечно, вариант.... Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"? Я так подозреваю, что никак. Зря Вы так... Дерево по данным SQL-запроса строится в "нормальных" серверах БД (Oracle, вроде бы должна быть такая фича в M$ SQL Server) на "ура". Надо только прочитать документацию... Ну, не знаю. Вот тут рядышком было обсуждение иерерхий с каким-то пессимистическим итогом. Да и хлопотно это все. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2008, 10:10 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
krvsa Николай1Предыдущий и последующий, это, конечно, вариант.... Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"? Я так подозреваю, что никак. Все мыслят в рамках своих БД и их возможностей... Как-то писал редактор программ и там использовал такой подход к "нумерации" строк программы - проблем не имел. Ведь программер, что работал с редактором, всегда видел строки от "начала" и до "конца" в правильной последовательности... "А у меня были программы со структурами" (С) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.03.2008, 10:11 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
mcureenab gpХраните порядок в real, равномерно от 1 до N + 1 Вариант ни чем не лучше нумерации интервалов с большим шагом и даже хуже, поскольку из-за ошибок округления и потери точности можно легко получить неожиданный результат. Короче нумеруйте интервалы целыми числами с большим шагом, чтобы зарезервировать место для дальнейших вставок, по мере надобности перенумеровывайте. Перенумеровывать скорее всего придётся не часто, если вообще придётся, а запросы к таким данным будут простые и эффективные. В зависимости от конкретной БД можно придумать более экзотические варианты, например на базе пользовательских типов. Но почти наверняка экзотика будет во всём проигрывать дедовским методам. С "дедовскими" методами - к терапевту. Оставим мистический трепет - округление при делении свойственно целым числам не в меньшей степени, чем дробным, просто нужно знать, какая у вас используется мантисса. Вам всеравно придется переупорядочивать, только это "иногда" будет стоить дополнительного гимороя, и усложнения логики. Лучше переупорядочивать всегда после вставки. Вообще я и сам знаю, что целочисленный метод легче понять. Не знаете как с плавающими работать, работайте с целыми. По сути, это не меняет алгоритма, просто за норму (единицу) принимается 2^(битность целого/2), и нумеровать при вставке можно без дробей, через один. берется 16 битное целое, шаг - 256. Максимальное хранение - 254 сегмента, вставка - до 254 за раз. Или берется 32 битное целое. Хранилище - 65534, вставка - максимум по 65634 элемента. По моему - достаточно, и не дорого. Алгоритм 2. Бинарная вставка. Вставлять можно только по 1 записи. Выбираете шаг 2^P. Это изначальный шаг, или - после переупорядочивания. В таблице дорог храните счетчик вставок до упорядочивания. Пред вставкой проверяете счетчик, если он достиг P-1, то восстанавливаете интервалы. Вставляете по 1 строчке, деля интервал пополам, увеличиваете счетчик для дороги. Экономия на перетряхиваниях индекса - в P-1 раз. Тоесть если выбрать шаг 65536, то гарантированно вставить без переупорядочивания можно 15 раз. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.03.2008, 18:47 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Сори - не так. Счетчика не надо, Просто оценивается интервал при вставке, если он мал, то предпринимается переупорядочивание. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.03.2008, 19:25 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
gpВообще я и сам знаю, что целочисленный метод легче понять. Не знаете как с плавающими работать, работайте с целыми. По сути, это не меняет алгоритма, просто за норму (единицу) принимается 2^(битность целого/2), и нумеровать при вставке можно без дробей, через один. Целочисленный метод понять наверное даже сложнее, но только на уровне математики. Когда дело касается вычислений всё наоборот. Так вспомним, что в оракле используется 100ричная арифметика, а многие двоичные дроби в десятичные точно не переводятся, в добавок потерю точности в арифметике с плавающей точкой не так просто обнаружить. В общем метод с математической точки зрения красивый, но для компьютерных вычислений малопригодный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.03.2008, 01:11 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
gp Вам всеравно придется переупорядочивать Не факт. Если размазать индексы участка по множеству целых чисел [1,.. 10^38], то такой участок можно будет гарантированно делить пополам более 100 раз без переупорядочивания. Может статься, что это позволит запускать процедуру перенумерации в рамках регламентных работ, как, например, перестройку индексов БД по ночам. gp, только это "иногда" будет стоить дополнительного гимороя, и усложнения логики. Да логика, то вроде не хитрая. Если очередой интервал не делится, начинаем перенумерацию. В принципе, можно даже перенумеровывать не все записи, а перед разбиением участка объеденить его с соседним участком, и попытаться разбить полученный интервал на три части и т.д. до победы. Правда такой замысловатый алгоритм может в конечном итоге проиграть тополному алгоритму полной перенумерации, который можно выполнить одним update. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.03.2008, 01:56 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
В общем, мы уже говорим об одном и том же давно. про "может статься" и регламентные работы вы загнули, надо сказать. Кстати, если использовать 32 битное целое (у вас - 38байт), то вероятность переупорядочивания = 1/15 в самом худшем случае (вставка в одно и то же место), а при равномерных вставках, и длине существующей коллекции 100 сегментов - меньше тысячной. Алгоритм с локальным анализом прилежащей области существует, и даже не нужно рекурсии. Нужно просто выбрать целочисленный "коофициент улучшения" Q > 2, и найти такой отрезок, который позволяет все элменты в этом отрезке расположить на расстоянии не меньше Q друг от друга. Это делается в один запрос и один апдейт. Для данной задачи этого скорее всего не нужно, но для очень больших постоянно упорядоченных списков - незаменимо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.03.2008, 04:06 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
Господа, а может быть подойдет решение со строкой: 1, 2,3,4 , 5 разбиваем участок 2 на 2 под-участка 1, 2.1, 2.2, 3, 4, 5 и т.д. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.03.2008, 07:17 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
drevГоспода, а может быть подойдет решение со строкой Данные желательно брать из полей сразу, не используя всякие вырезки и пр. операции... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.03.2008, 08:28 |
|
||
|
Вставка с сохранением порядка
|
|||
|---|---|---|---|
|
#18+
А что если использовать для нумерации простые дроби такое как: 1/2 3/4...и т.д, а числитель и знаменатель хранить в разных(2-х) полях Пример: 1. ввел два участка: А(0) и В(1) 2. теперь надо ввести участок С наприсем между А и В высчитываем дробь С=0+1/2=1/2 получаем А(0), с(1/2), В(1) 3. А теперь надо ввести 3 участка D, E, F например между С и В новый_дроб_номер=B+(B-C)/(кол_во_ввод_участвок+1)*поряд_номер_новых_участков // D-1, E-2, F-3 Считаем: D=1/2+(1-1/2)/(3+1)*1=5/8 E=1/2+(1-1/2)/(3+1)*2=6/8 F =1/2+(1-1/2)/(3+1)*3=7/8 Итого получаем A(0), C(1/2), D(5/8), E(6/8), F(7/8), B(1) вообщем такая идея... З.Ы. а в таблице можно создать 3-е результирующие поле типа DOUBLE равное отношению числ/знам, и собственно по иму сортировать З.З.Ы правда надо реализовать некоторые элемен функции по работе с простыми дробями, но это будет дешевле чем перебор/измен всех записей мож пойдет такой вариант...... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.03.2008, 11:05 |
|
||
|
|

start [/forum/topic.php?fid=32&msg=35196811&tid=1543965]: |
0ms |
get settings: |
9ms |
get forum list: |
21ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
404ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
69ms |
get tp. blocked users: |
2ms |
| others: | 270ms |
| total: | 794ms |

| 0 / 0 |
