Алгоритм контроля версий

У меня есть база данных, в которой я храню объекты. У меня следующая (упрощенная) схема

CREATE TABLE MyObjects
(
  UniqueIdentifier Id;
  BigInt           GenerationId;
  BigInt           Value;
  Bit              DeleteAction;
)

Каждый объект имеет уникальный идентификатор («Id») и (набор) свойств («Value»). Каждый раз, когда значение свойства объекта изменяется, я ввожу новую строку в эту таблицу с идентификатором нового поколения («GenerationId», который монотонно увеличивается). Если объект удален, я фиксирую этот факт, устанавливая бит «DeleteAction» в значение true.

В любой момент времени (генерации) я хотел бы получить состояние всех моих активных объектов!

Вот пример:

Id    GenerationId Value  DeleteAction
1        1          99       false
2        1          88       false
1        2          77       false
2        3          88       true

Объекты в поколениях:

  1: 1 {99}, 2 {88}
  2: 1 {77}, 2 {88}
  3: 1 {77}

Ключ: как мне узнать строку для каждого уникального объекта, который является идентификатор поколения наиболее близок (но не превышает) к заданному идентификатору поколения? Затем я могу выполнить этап постфильтра, чтобы удалить все строки, в которых значение поля DeleteAction истинно.

Я не слежу за вашим примером «Объекты в поколениях». Не могли бы вы уточнить.

Gavin Miller 02.12.2008 02:18

В примере допущена опечатка, похоже, generationID 1 используется дважды.

bortzmeyer 04.12.2008 13:48

Нет, целью было показать, что оба объекта 1 и 2 добавляются в одном поколении 1. Примером из системы управления версиями может быть добавление 2 файлов в набор изменений, где поколение - это номер набора изменений.

Philipp Schmid 05.12.2008 22:06
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
788
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Не уверен, что это стандартный SQL, но в Postgres вы можете использовать флаг LIMIT:

 select GenerationId,Value,DeleteAction from MyObjects 
    where Id=1 and GenerationId < 3 
    order by GenerationId
    limit 1;

Суть вопроса заключалась не в том, чтобы указывать Id = 1, а скорее возвращать все идентификаторы, которые соответствуют требованиям генерации.

Philipp Schmid 02.12.2008 11:33

Это работает в MS SQL

SELECT id,value
FROM Myobjects
INNER JOIN ( 
     SELECT id, max(GenerationID) as LastGen 
     FROM MyObjects
     WHERE GenerationID <= @Wantedgeneration
     Group by ID)
    On GenerationID = LastGen
WHERE DelectedAction = false

Ага, это должно сработать. По крайней мере, это хорошая отправная точка. +1;)

sindre j 02.12.2008 13:06

Моя версия использует соединение таблицы MyObjects с подмножество самого себя, созданное подзапросом и содержащее только последний генерация для каждого объекта:

SELECT O.id,generation,value FROM 
     MyObjects O, 
     (SELECT id,max(generation) AS max_generation FROM MyObjects 
     WHERE generation <= $GENERATION_ID GROUP BY id) AS TheMax WHERE 
            TheMax.max_generation = generation AND O.deleted is False
     ORDER BY generation DESC;

В приведенном выше запросе GENERATION_ID зашит. Способ параметризация - написать функцию:

CREATE OR REPLACE FUNCTION generation_objects(INTEGER) RETURNS SETOF MyObjects AS
  'SELECT O.id,generation,value,deleted FROM 
       MyObjects O, 
       (SELECT id,max(generation) AS max_generation FROM MyObjects 
       WHERE generation <= $1 GROUP BY id) AS TheMax WHERE 
              TheMax.max_generation = generation AND O.deleted is False;'
  LANGUAGE SQL;

Теперь это работает. С этой таблицей:

> SELECT * FROM MyObjects;          
 id | generation | value | deleted 
----+------------+-------+---------
  1 |          1 |    99 | f
  2 |          2 |    88 | f
  1 |          3 |    77 | f
  2 |          4 |    88 | t
  3 |          5 |    33 | f
  4 |          6 |    22 | f
  3 |          7 |    11 | f
  2 |          8 |    11 | f

Я получил:

> SELECT * FROM generation_objects(1) ORDER by generation DESC;
 id | generation | value | deleted 
----+------------+-------+---------
  1 |          1 |    99 | f

> SELECT * FROM generation_objects(2) ORDER by generation DESC;
 id | generation | value | deleted 
----+------------+-------+---------
  2 |          2 |    88 | f
  1 |          1 |    99 | f

> SELECT * FROM generation_objects(3) ORDER by generation DESC;
 id | generation | value | deleted 
----+------------+-------+---------
  1 |          3 |    77 | f
  2 |          2 |    88 | f

А затем, при следующем поколении, объект 2 удаляется:

> SELECT * FROM generation_objects(4) ORDER by generation DESC;
 id | generation | value | deleted 
----+------------+-------+---------
  1 |          3 |    77 | f
Ответ принят как подходящий

Вот рабочая версия:

SELECT MyObjects.Id,Value
FROM Myobjects
INNER JOIN 
(      
  SELECT Id, max(GenerationId) as LastGen
  FROM MyObjects
  WHERE GenerationId <= @TargetGeneration
  Group by Id
) T1
ON MyObjects.Id = T1.Id AND MyObjects.GenerationId = LastGen
WHERE DeleteAction = 'False'

Другие вопросы по теме