2008-12-01 8 views
3

J'ai une base de données dans laquelle je stocke des objets. Je le schéma suivant (simplifié)Algorithme de contrôle de version

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

Chaque objet possède un identifiant unique ("Id"), et un (ensemble de) propriété ("Value"). Chaque fois que la valeur de la propriété d'un objet est modifiée, j'entre une nouvelle ligne dans cette table avec un nouvel identifiant de génération ("GenerationId", qui augmente de façon monotone). Si un objet est supprimé, j'enregistre ce fait en mettant le bit "DeleteAction" à true.

À tout moment (génération), je voudrais récupérer l'état de tous mes objets actifs!

Voici un exemple:

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

Objets générations sont:

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

La clé est: comment puis-je trouver la ligne pour chaque objet unique qui est id de génération est la plus proche (mais ne dépassant pas) à un identifiant de génération donné? Je peux ensuite faire une étape post-filtre pour supprimer toutes les lignes où le champ DeleteAction est vrai.

+0

Je ne suis pas l'exemple de vos objets dans les générations. Pourriez-vous clarifier. –

+0

Il y a une faute de frappe dans l'exemple, il semble que l'ID génération 1 est utilisé deux fois. – bortzmeyer

+0

Non, le but était de montrer que les objets 1 et 2 sont ajoutés dans la même génération 1. Un exemple du contrôle de source serait d'ajouter 2 fichiers dans un ensemble de modifications, où la génération est le nombre de changeset. –

Répondre

1

Voici la version de travail:

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' 
0

Je ne sais pas si c'est la norme SQL, mais dans Postgres, vous pouvez utiliser le drapeau LIMIT:

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

Le point de la question n'était pas de spécifier Id = 1, mais plutôt de renvoyer tous les ID correspondant à l'exigence de génération. –

+0

Malheureusement, ce n'était pas clair à partir de la question. –

4

Cela fonctionne dans 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 
+0

Yup, ça devrait faire l'affaire. Au moins, c'est un bon point de départ. +1;) –

2

Ma version utilise un joint de la table MyObjects contre un sous-ensemble de lui-même, créé par une sous-requête, et contenant uniquement la dernière génération pour chaque objet:

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; 

Dans la requête ci-dessus, le paramètre GENERATION_ID est câblé. Une façon de il est d'Paramétrer écrire une fonction:

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; 

Maintenant, cela fonctionne. Avec ce tableau:

> 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 

Je reçois:

> 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 

Et puis, à la génération suivante, objet 2 est supprimé:

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