У меня есть база данных, в которой я храню объекты. У меня следующая (упрощенная) схема
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 истинно.
В примере допущена опечатка, похоже, generationID 1 используется дважды.
Нет, целью было показать, что оба объекта 1 и 2 добавляются в одном поколении 1. Примером из системы управления версиями может быть добавление 2 файлов в набор изменений, где поколение - это номер набора изменений.





Не уверен, что это стандартный SQL, но в Postgres вы можете использовать флаг LIMIT:
select GenerationId,Value,DeleteAction from MyObjects
where Id=1 and GenerationId < 3
order by GenerationId
limit 1;
Суть вопроса заключалась не в том, чтобы указывать Id = 1, а скорее возвращать все идентификаторы, которые соответствуют требованиям генерации.
Это работает в 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;)
Моя версия использует соединение таблицы 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'
Я не слежу за вашим примером «Объекты в поколениях». Не могли бы вы уточнить.