我有一个存储对象的数据库。我有以下(简化)架构
CREATE TABLE MyObjects
(
UniqueIdentifier Id;
BigInt GenerationId;
BigInt Value;
Bit DeleteAction;
)
每个对象都有一个唯一标识符(“Id”)和一个(一组)属性(“Value”)。每次更改对象的属性值时,我都会在此表中输入一个新行,其中包含一个新生成ID(“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}
关键是:如何找出生成ID最接近(但不超过)给定代ID 的每个唯一对象的行?然后,我可以执行后过滤步骤以删除DeleteAction字段为true的所有行。
答案 0 :(得分:4)
这适用于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 :(得分:2)
我的版本使用表MyObjects与a的联合 自身的子集,由子查询创建,仅包含最后一个 每个对象的生成:
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
答案 2 :(得分:1)
这是工作版本:
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'
答案 3 :(得分:0)
不确定这是否是标准SQL,但在Postgres中,您可以使用LIMIT标志:
select GenerationId,Value,DeleteAction from MyObjects
where Id=1 and GenerationId < 3
order by GenerationId
limit 1;