【问题标题】:Version Control Algorithm版本控制算法
【发布时间】:2008-12-01 23:10:32
【问题描述】:

我有一个存储对象的数据库。我有以下(简化的)架构

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 的所有行。

【问题讨论】:

  • 我没有关注您的世代对象示例。你能澄清一下吗?
  • 例子中有错别字,好像是generationID 1用了两次。
  • 不,关键是要表明对象 1 和 2 都添加在同一代 1 中。源代码管理的一个示例是在变更集中添加 2 个文件,其中代是变更集编号.

标签: c# sql algorithm


【解决方案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 ;)
【解决方案2】:

我的版本使用表 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

【讨论】:

    【解决方案3】:

    这是工作版本:

    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'
    

    【讨论】:

      【解决方案4】:

      不确定这是否是标准 SQL,但在 Postgres 中,您可以使用 LIMIT 标志:

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

      【讨论】:

      • 问题的重点不是必须指定Id=1,而是返回所有符合生成要求的Id。
      猜你喜欢
      • 2010-10-01
      • 2011-02-16
      • 2011-03-08
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 2011-05-12
      • 2010-10-30
      • 2014-08-15
      相关资源
      最近更新 更多