powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Вставка с сохранением порядка
25 сообщений из 29, страница 1 из 2
Вставка с сохранением порядка
    #35193362
Фотография wellwell
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Имеются две таблицы, ROADS (дороги) и секции (SECTIONS), связаны один ко многим, так что дорога состоит из некого числа участков:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE TABLE ROAD (
    ID         INTEGER NOT NULL PRIMARY KEY,
    ROAD_NAME  VARCHAR( 128 ) NOT NULL
);

CREATE TABLE SECTION (
    ID            INTEGER NOT NULL PRIMARY KEY ,
    ROAD_ID       INTEGER NOT NULL,
    SPEED_LIMIT   INTEGER NOT NULL,
    FOREIGN KEY (ROAD_ID) REFERENCES ROAD (ID)
);

Изначально пользователь вводит дорогу (ее имя) и затем множество участков из которых эта дорога состоит, при этом каждый участок характеризуется собственным ограничением скорости. Участки должны идти в неком порядке (соседние номера не обязательно должны отличаться на единицу, главное, чтобы они возрастали от начала к концу). Когда пользователь вводит их подряд, от начала дороги до ее конца, проблем нет, т.к. ID секций идут последовательно.

Однако, позже пользователь может разбить один или более участков. Например, если у нас были участки с ID 1,2,3,4,5, и пользователь захотел разбить участок 3 на два более коротких фрагмента с различными ограничениями скорости движения. Понятно что если просто получить новый ID, для нового участка, он будет равен 6, и порядок следования секций будет нарушен. Вставить участок с ID 3.5 тоже нельзя, т.к. поле целочисленное.

Можно, конечно, нумеровать участки с неким запасом, скажем, 100, 200, 300, 400, 500..., и в случае необходимости вставлять новые записи в зазор, например с ID 350, но может имеются какие-то более удачные решения?

Эти идентификаторы используются пользователем и он не должен перенумеровать записи вручную при вставке. Есть идеи как сделать это оптимально?
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35193391
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы использовал отдельные поля для идентификации отрезков и для указания порядка их следования и пересчитывал второе из них при вставке/разбиении участков в пределах данной дороги. Пересчитывать можно либо сразу при вставке, либо вставлять промежуточное значение (например 350 между 300 и 400) и периодически пересчитывать, чтобы восстановить исходные интервалы нумерации (например, через 100).
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35194499
Bely
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftЯ бы использовал отдельные поля для идентификации отрезков и для указания порядка их следования+1
Это стандартный подход.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35196605
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А может быть здесь нужен граф?
тут ведь дороги не что-то само по себе... они ведь пересекаются, разветвляются (узлы), а скоростные участки между "узлами" - вес ребра...
ну и хранить...
что-то типа
Код: plaintext
1.
2.
3.
4.
ID   Node1   Node2   Speed
1     2       3      60
2     3       4      60
3     4       5      80
и всё это к вашей задаче прикрутить
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35196811
КифирчикА может быть здесь нужен граф?
тут ведь дороги не что-то само по себе... они ведь пересекаются, разветвляются (узлы), а скоростные участки между "узлами" - вес ребра...
ну и хранить...
что-то типа
Код: plaintext
1.
2.
3.
4.
ID   Node1   Node2   Speed
1     2       3      60
2     3       4      60
3     4       5      80
и всё это к вашей задаче прикрутить
А может сделать "стандартно" - добавить поле РarentID и уже по нему строить дерево. У "корня" будет ParentID = 0 (или NULL).

Добавлю (к любым вариантам):
надо будет действовать так же, как при вставке в середину связного списка: корректировать ссылки на следующий / предыдущий элементы как у вставляемого элемента, так и предшествующего ему и у следующего за ним.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35197220
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Станислав С...кийА может сделать "стандартно" - добавить поле РarentID и уже по нему строить дерево. У "корня" будет ParentID = 0 (или NULL).
м.. родитель... корень... это ведь "сеть", какой здесь корень?
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35197304
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кифирчик , все дороги ведут в Рим. (с) Вот его-то и можно взять за корень.
А идея с пропиской "предыдущего" и "последующего" - неплохой вариант...
----------
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
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35200010
Николай1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa Кифирчик , все дороги ведут в Рим. (с) Вот его-то и можно взять за корень.
А идея с пропиской "предыдущего" и "последующего" - неплохой вариант...


Предыдущий и последующий, это, конечно, вариант....
Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"?
Я так подозреваю, что никак.

Думаю, что нумеровать "с дырками" и, при необходимости, перенумеровывать - не самый плохой и трудоемкий вариант. Особенно, если не делать к этому порядковому номеру никаких привязок. Выполняют же балансировку индексов и ничего, все живы, никто не умирает.

А "предыдущий/следующий" - это столько гимора...
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35200104
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Николай1Предыдущий и последующий, это, конечно, вариант....
Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"?
Я так подозреваю, что никак.
Все мыслят в рамках своих БД и их возможностей...

Как-то писал редактор программ и там использовал такой подход к "нумерации" строк программы - проблем не имел.
Ведь программер, что работал с редактором, всегда видел строки от "начала" и до "конца" в правильной последовательности...
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35200114
Николай1
Предыдущий и последующий, это, конечно, вариант....
Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"?
Я так подозреваю, что никак.

Зря Вы так... Дерево по данным SQL-запроса строится в "нормальных" серверах БД (Oracle, вроде бы должна быть такая фича в M$ SQL Server) на "ура". Надо только прочитать документацию...
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35200196
Фотография Dogen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Станислав С...кий
надо будет действовать так же, как при вставке в середину связного списка: корректировать ссылки на следующий / предыдущий элементы как у вставляемого элемента, так и предшествующего ему и у следующего за ним.
этто как расс необязаттельно

достаточно вдвое меньше данных, зачем дублировать?
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35204595
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лучше всего будет, как и всегда, найти натуральный порядок для сегментов, если есть где взять, например - расстояние в метрах от начала дороги.

Если нету - оцените, как часто будут добавляться сегменты.
Если редко - то тоже есть лучшее решение.
Храните порядок в 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.
with segs as
(
	select ID, RoadID, ROW_NUMBER() OVER(ORDER BY OrderSK) as NewOrderSK from RoadSegments where RoadID=@RoadID
)
update RoadSegments set OrderSK = new_segs.NewOrderSK
from RoadSegments as rs
inner join segs as new_segs on rs.ID = new_segs.ID
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35204626
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забыл сказать, почему это лучше, - это резко упрощает логику.

1. Например интервал в 100 целых можно поделить надвое только 6 раз.
2. Есть ограничение в 99 вставок за раз, хотя и неактуально, но всеже - придется о нем помнить.
3. Получаете порядковый номер "бесплатно". В случае запасного интервала порядок будет стоить дополнительного запроса.

Есть все же ограничение, следует помнить о нем.
если у вас уже есть примерно 10 миллионов сегментов, то можно вставить за раз еще только 10 миллионов сегментов, не больше - мантисса не позволит :)
Если это для вас плохое ограничение, то используйте double :)
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35207139
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gpХраните порядок в real, равномерно от 1 до N + 1


Вариант ни чем не лучше нумерации интервалов с большим шагом и даже хуже, поскольку из-за ошибок округления и потери точности можно легко получить неожиданный результат. Короче нумеруйте интервалы целыми числами с большим шагом, чтобы зарезервировать место для дальнейших вставок, по мере надобности перенумеровывайте. Перенумеровывать скорее всего придётся не часто, если вообще придётся, а запросы к таким данным будут простые и эффективные.


В зависимости от конкретной БД можно придумать более экзотические варианты, например на базе пользовательских типов. Но почти наверняка экзотика будет во всём проигрывать дедовским методам.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35207330
Николай1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Станислав С...кий Николай1
Предыдущий и последующий, это, конечно, вариант....
Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"?
Я так подозреваю, что никак.

Зря Вы так... Дерево по данным SQL-запроса строится в "нормальных" серверах БД (Oracle, вроде бы должна быть такая фича в M$ SQL Server) на "ура". Надо только прочитать документацию...

Ну, не знаю.
Вот тут рядышком было обсуждение иерерхий с каким-то пессимистическим итогом.
Да и хлопотно это все.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35207331
Николай1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsa Николай1Предыдущий и последующий, это, конечно, вариант....
Только вот как для данного варианта получить список всех участков дороги в заданном порядке "одним запросом"?
Я так подозреваю, что никак.
Все мыслят в рамках своих БД и их возможностей...

Как-то писал редактор программ и там использовал такой подход к "нумерации" строк программы - проблем не имел.
Ведь программер, что работал с редактором, всегда видел строки от "начала" и до "конца" в правильной последовательности...

"А у меня были программы со структурами" (С)
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208375
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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 раз.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208404
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сори - не так.
Счетчика не надо,
Просто оценивается интервал при вставке, если он мал, то предпринимается переупорядочивание.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208616
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gpВообще я и сам знаю, что целочисленный метод легче понять. Не знаете как с плавающими работать, работайте с целыми. По сути, это не меняет алгоритма, просто за норму (единицу) принимается 2^(битность целого/2), и нумеровать при вставке можно без дробей, через один.

Целочисленный метод понять наверное даже сложнее, но только на уровне математики. Когда дело касается вычислений всё наоборот. Так вспомним, что в оракле используется 100ричная арифметика, а многие двоичные дроби в десятичные точно не переводятся, в добавок потерю точности в арифметике с плавающей точкой не так просто обнаружить. В общем метод с математической точки зрения красивый, но для компьютерных вычислений малопригодный.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208628
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gp
Вам всеравно придется переупорядочивать


Не факт. Если размазать индексы участка по множеству целых чисел [1,.. 10^38], то такой участок можно будет гарантированно делить пополам более 100 раз без переупорядочивания. Может статься, что это позволит запускать процедуру перенумерации в рамках регламентных работ, как, например, перестройку индексов БД по ночам.

gp, только это "иногда" будет стоить дополнительного гимороя, и усложнения логики.

Да логика, то вроде не хитрая. Если очередой интервал не делится, начинаем перенумерацию. В принципе, можно даже перенумеровывать не все записи, а перед разбиением участка объеденить его с соседним участком, и попытаться разбить полученный интервал на три части и т.д. до победы. Правда такой замысловатый алгоритм может в конечном итоге проиграть тополному алгоритму полной перенумерации, который можно выполнить одним update.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208649
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, мы уже говорим об одном и том же давно.

про "может статься" и регламентные работы вы загнули, надо сказать.

Кстати, если использовать 32 битное целое (у вас - 38байт), то вероятность переупорядочивания = 1/15 в самом худшем случае (вставка в одно и то же место), а при равномерных вставках, и длине существующей коллекции 100 сегментов - меньше тысячной.

Алгоритм с локальным анализом прилежащей области существует, и даже не нужно рекурсии. Нужно просто выбрать целочисленный "коофициент улучшения" Q > 2, и найти такой отрезок, который позволяет все элменты в этом отрезке расположить на расстоянии не меньше Q друг от друга. Это делается в один запрос и один апдейт.

Для данной задачи этого скорее всего не нужно, но для очень больших постоянно упорядоченных списков - незаменимо.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208703
drev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Господа, а может быть подойдет решение со строкой:

1, 2,3,4 , 5

разбиваем участок 2 на 2 под-участка

1, 2.1, 2.2, 3, 4, 5

и т.д.
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35208741
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
drevГоспода, а может быть подойдет решение со строкой
Данные желательно брать из полей сразу, не используя всякие вырезки и пр. операции...
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35209040
А что если использовать для нумерации простые дроби такое как: 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 равное отношению числ/знам,
и собственно по иму сортировать

З.З.Ы правда надо реализовать некоторые элемен функции по работе с простыми дробями, но это будет дешевле чем перебор/измен всех записей
мож пойдет такой вариант......
...
Рейтинг: 0 / 0
Вставка с сохранением порядка
    #35209385
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Камимуравообщем такая идея...
А как потом понять что означают N/M у какой-то конкретной записи?
...
Рейтинг: 0 / 0
25 сообщений из 29, страница 1 из 2
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Вставка с сохранением порядка
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]