none
Selezionare solo ultime Versioni RRS feed

  • Domanda

  • Salve a tutti
    Se io avessi questa tabella

    CREATE TABLE [dbo].[Descriptions](
     [ID] [uniqueidentifier] NOT NULL,
     [PreviousID] [uniqueidentifier] NULL,
     [Version] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL,
     CONSTRAINT [PK_Description] PRIMARY KEY
    (
     [ID] ASC
    )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

     

    ALTER TABLE [dbo].[Descriptions] WITH CHECK ADD CONSTRAINT [FK_Descriptions_Descriptions] FOREIGN KEY([PreviousID])
    REFERENCES [dbo].[Descriptions] ([ID])

    Dove PreviousID è una foreign key sul campo ID della stessa tabella per gestire il versioning di un testo(ad esempio il campo descrizione)

    avento i seguenti dati di prova, con due elementi, element A con tre versioni e element B con due versioni

    Delete from Descriptions;
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088365',NULL,'Element A Version1');
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088366','3847fc93-256e-4065-b392-4131b9088365','Element A Version2');
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088367','3847fc93-256e-4065-b392-4131b9088366','Element A Version3');
    
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088368',NULL,'Element B Version1');
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088369','3847fc93-256e-4065-b392-4131b9088368','Element B Version2');


    In che modo posso scrivere una query di select(da C# se è possibile:)) che mi prenda solo le ultime versioni degli elementi?


    ciao e grazie

    lunedì 25 ottobre 2010 13:00

Risposte

  • Osserva il seguente esempio:

    WITH CTE_Descriptions(ID, [Level]) AS
    (
      SELECT ID, 0
      FROM dbo.Descriptions
      WHERE PreviousID IS NULL
      
      UNION ALL
      
      SELECT D.ID, C.[Level] + 1
      FROM dbo.Descriptions AS D
      JOIN CTE_Descriptions AS C
      ON D.PreviousID = C.ID
    )
    , CTE_DefineGroups(ID, GroupID) AS
    (
      SELECT ID, ROW_NUMBER() OVER (ORDER BY ID) - [Level]
      FROM CTE_Descriptions
    )
    , CTE_GetKey(ID) AS
    (
      SELECT MAX(CAST(ID AS varchar(36)))
      FROM CTE_DefineGroups
      GROUP BY GroupID
    )
    SELECT D.*
    FROM dbo.Descriptions AS D
    JOIN CTE_GetKey AS C
    ON D.ID = C.ID
    ORDER BY D.ID;
    
    /* Output:
    
    ID                  PreviousID              Version
    ------------------------------------ ------------------------------------ -------------------
    3847FC93-256E-4065-B392-4131B9088367 3847FC93-256E-4065-B392-4131B9088366 Element A Version3
    3847FC93-256E-4065-B392-4131B9088369 3847FC93-256E-4065-B392-4131B9088368 Element B Version2
    
    (2 row(s) affected)
    
    */

    In pratica utilizzo una CTE ricorsiva per assegnare un "livello" alle varie versioni di un elemento, una seconda CTE per assegnare un ID numerico per ogni gruppo di elementi, una ulteriore CTE per restituire l'ID delle versioni più recenti ed una ultima query per recuperare tutti i dati di quegli ID.

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.microsoft.com/Forums/it-IT/sqlserverit

    • Contrassegnato come risposta G Luca martedì 26 ottobre 2010 09:08
    lunedì 25 ottobre 2010 14:37
    Moderatore
  • altra solutzione :

    ;with cte as
    (
    select ID ,ID as PreviousID,1 as [Level]
    from Descriptions where PreviousID is null 
    union all
    select c.ID,F.ID,[Level]+1
    from Descriptions F 
    inner join cte c on c.PreviousID = F.PreviousID 
    )
    select C.ID,
    case
    when C.ID = C.PreviousID then null 
    else C.PreviousID
    end as GrandID
    from cte c 
    inner join (select ID,max(Level) as [Level] from cte group by ID)t on c.ID = t.ID and c.Level = t.Level
    
     

    Best regards
    • Contrassegnato come risposta G Luca martedì 26 ottobre 2010 09:08
    lunedì 25 ottobre 2010 16:53
  • Quindi la soluzione finale dovrebbe essere

    with cte as
    (
    select ID ,ID as PreviousID,1 as [Level]
    from Descriptions where PreviousID is null 
    union all
    select c.ID,F.ID,c.[Level]+1
    from Descriptions F 
    inner join cte c on c.PreviousID = F.PreviousID 
    ),
     sel_ID as
    (
    select C.PreviousID as ID
    from cte c 
    inner join 
    (select ID,max(Level) as [Level] from cte group by ID)t 
    on c.ID = t.ID and c.Level = t.Level
    )
    select descriptions.* from descriptions inner join sel_ID on descriptions.id=sel_ID.id
    
    sembra funzionare
    • Contrassegnato come risposta G Luca martedì 26 ottobre 2010 09:09
    lunedì 25 ottobre 2010 18:25

Tutte le risposte

  • Ciao, prova questo query :

    select ID,max(version) from Descriptions group by ID
    

     

     

     


    Best regards
    lunedì 25 ottobre 2010 13:15
  • Ciao, prova questo query :

    select ID,max(version) from Descriptions group by ID
    
    

     

     

     


    Best regards

    Ciao,

    I valori di Description sono solo da esempio, non è detto che siano ordinati secondo la versione, ci potrebbe essere Zaino nella prima versione e Borsa nella seconda

    Comunque, il campo Description è presente solo per far rendere l'idea in realtà mi interessa qualcosa che agisca sulla struttura degli ID/PreviousID

    lunedì 25 ottobre 2010 13:18
  • In che modo posso scrivere una query di select(da C# se è possibile:)) che mi prenda solo le ultime versioni degli elementi?

    Quale deve essere il result set risultante con i dati di prova che hai postato? (righe e colonne)

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.microsoft.com/Forums/it-IT/sqlserverit
    lunedì 25 ottobre 2010 13:26
    Moderatore
  • Ciao,

    Il terzo insert e il quinto insert

    lunedì 25 ottobre 2010 13:28
  • Osserva il seguente esempio:

    WITH CTE_Descriptions(ID, [Level]) AS
    (
      SELECT ID, 0
      FROM dbo.Descriptions
      WHERE PreviousID IS NULL
      
      UNION ALL
      
      SELECT D.ID, C.[Level] + 1
      FROM dbo.Descriptions AS D
      JOIN CTE_Descriptions AS C
      ON D.PreviousID = C.ID
    )
    , CTE_DefineGroups(ID, GroupID) AS
    (
      SELECT ID, ROW_NUMBER() OVER (ORDER BY ID) - [Level]
      FROM CTE_Descriptions
    )
    , CTE_GetKey(ID) AS
    (
      SELECT MAX(CAST(ID AS varchar(36)))
      FROM CTE_DefineGroups
      GROUP BY GroupID
    )
    SELECT D.*
    FROM dbo.Descriptions AS D
    JOIN CTE_GetKey AS C
    ON D.ID = C.ID
    ORDER BY D.ID;
    
    /* Output:
    
    ID                  PreviousID              Version
    ------------------------------------ ------------------------------------ -------------------
    3847FC93-256E-4065-B392-4131B9088367 3847FC93-256E-4065-B392-4131B9088366 Element A Version3
    3847FC93-256E-4065-B392-4131B9088369 3847FC93-256E-4065-B392-4131B9088368 Element B Version2
    
    (2 row(s) affected)
    
    */

    In pratica utilizzo una CTE ricorsiva per assegnare un "livello" alle varie versioni di un elemento, una seconda CTE per assegnare un ID numerico per ogni gruppo di elementi, una ulteriore CTE per restituire l'ID delle versioni più recenti ed una ultima query per recuperare tutti i dati di quegli ID.

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.microsoft.com/Forums/it-IT/sqlserverit

    • Contrassegnato come risposta G Luca martedì 26 ottobre 2010 09:08
    lunedì 25 ottobre 2010 14:37
    Moderatore
  • Osserva il seguente esempio:

    WITH CTE_Descriptions(ID, [Level]) AS
    
    (
    
     SELECT ID, 0
    
     FROM dbo.Descriptions
    
     WHERE PreviousID IS NULL
    
     
    
     UNION ALL
    
     
    
     SELECT D.ID, C.[Level] + 1
    
     FROM dbo.Descriptions AS D
    
     JOIN CTE_Descriptions AS C
    
     ON D.PreviousID = C.ID
    
    )
    
    , CTE_DefineGroups(ID, GroupID) AS
    
    (
    
     SELECT ID, ROW_NUMBER() OVER (ORDER BY ID) - [Level]
    
     FROM CTE_Descriptions
    
    )
    
    , CTE_GetKey(ID) AS
    
    (
    
     SELECT MAX(CAST(ID AS varchar(36)))
    
     FROM CTE_DefineGroups
    
     GROUP BY GroupID
    
    )
    
    SELECT D.*
    
    FROM dbo.Descriptions AS D
    
    JOIN CTE_GetKey AS C
    
    ON D.ID = C.ID
    
    ORDER BY D.ID;
    
    
    
    /* Output:
    
    
    
    ID         PreviousID       Version
    
    ------------------------------------ ------------------------------------ -------------------
    
    3847FC93-256E-4065-B392-4131B9088367 3847FC93-256E-4065-B392-4131B9088366 Element A Version3
    
    3847FC93-256E-4065-B392-4131B9088369 3847FC93-256E-4065-B392-4131B9088368 Element B Version2
    
    
    
    (2 row(s) affected)
    
    
    
    */
    
    

    In pratica utilizzo una CTE ricorsiva per assegnare un "livello" alle varie versioni di un elemento, una seconda CTE per assegnare un ID numerico per ogni gruppo di elementi, una ulteriore CTE per restituire l'ID delle versioni più recenti ed una ultima query per recuperare tutti i dati di quegli ID.

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.microsoft.com/Forums/it-IT/sqlserverit


    Ciao,

    nella tua soluzione ci sono molte cose che non conosco e che non capisco. Cerco di documentarmi nu po e spero per domani di poterti dare un feedback.

    Grazie

    lunedì 25 ottobre 2010 15:56
  • Osserva il seguente esempio:

    WITH CTE_Descriptions(ID, [Level]) AS
    
    (
    
     SELECT ID, 0
    
     FROM dbo.Descriptions
    
     WHERE PreviousID IS NULL
    
     
    
     UNION ALL
    
     
    
     SELECT D.ID, C.[Level] + 1
    
     FROM dbo.Descriptions AS D
    
     JOIN CTE_Descriptions AS C
    
     ON D.PreviousID = C.ID
    
    )
    
    , CTE_DefineGroups(ID, GroupID) AS
    
    (
    
     SELECT ID, ROW_NUMBER() OVER (ORDER BY ID) - [Level]
    
     FROM CTE_Descriptions
    
    )
    
    , CTE_GetKey(ID) AS
    
    (
    
     SELECT MAX(CAST(ID AS varchar(36)))
    
     FROM CTE_DefineGroups
    
     GROUP BY GroupID
    
    )
    
    SELECT D.*
    
    FROM dbo.Descriptions AS D
    
    JOIN CTE_GetKey AS C
    
    ON D.ID = C.ID
    
    ORDER BY D.ID;
    
    
    
    /* Output:
    
    
    
    ID         PreviousID       Version
    
    ------------------------------------ ------------------------------------ -------------------
    
    3847FC93-256E-4065-B392-4131B9088367 3847FC93-256E-4065-B392-4131B9088366 Element A Version3
    
    3847FC93-256E-4065-B392-4131B9088369 3847FC93-256E-4065-B392-4131B9088368 Element B Version2
    
    
    
    (2 row(s) affected)
    
    
    
    */
    
    

    In pratica utilizzo una CTE ricorsiva per assegnare un "livello" alle varie versioni di un elemento, una seconda CTE per assegnare un ID numerico per ogni gruppo di elementi, una ulteriore CTE per restituire l'ID delle versioni più recenti ed una ultima query per recuperare tutti i dati di quegli ID.

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.microsoft.com/Forums/it-IT/sqlserverit


    Osserva il seguente esempio:

    WITH CTE_Descriptions(ID, [Level]) AS
    
    (
    
     SELECT ID, 0
    
     FROM dbo.Descriptions
    
     WHERE PreviousID IS NULL
    
     
    
     UNION ALL
    
     
    
     SELECT D.ID, C.[Level] + 1
    
     FROM dbo.Descriptions AS D
    
     JOIN CTE_Descriptions AS C
    
     ON D.PreviousID = C.ID
    
    )
    
    , CTE_DefineGroups(ID, GroupID) AS
    
    (
    
     SELECT ID, ROW_NUMBER() OVER (ORDER BY ID) - [Level]
    
     FROM CTE_Descriptions
    
    )
    
    , CTE_GetKey(ID) AS
    
    (
    
     SELECT MAX(CAST(ID AS varchar(36)))
    
     FROM CTE_DefineGroups
    
     GROUP BY GroupID
    
    )
    
    SELECT D.*
    
    FROM dbo.Descriptions AS D
    
    JOIN CTE_GetKey AS C
    
    ON D.ID = C.ID
    
    ORDER BY D.ID;
    
    
    
    /* Output:
    
    
    
    ID         PreviousID       Version
    
    ------------------------------------ ------------------------------------ -------------------
    
    3847FC93-256E-4065-B392-4131B9088367 3847FC93-256E-4065-B392-4131B9088366 Element A Version3
    
    3847FC93-256E-4065-B392-4131B9088369 3847FC93-256E-4065-B392-4131B9088368 Element B Version2
    
    
    
    (2 row(s) affected)
    
    
    
    */
    
    

    In pratica utilizzo una CTE ricorsiva per assegnare un "livello" alle varie versioni di un elemento, una seconda CTE per assegnare un ID numerico per ogni gruppo di elementi, una ulteriore CTE per restituire l'ID delle versioni più recenti ed una ultima query per recuperare tutti i dati di quegli ID.

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.microsoft.com/Forums/it-IT/sqlserverit


    Ciao,

    Ancora non padroneggio del tutto quello che hai scritto :) però sembra che faccia affidamento sul fatto che gli ID uniqueidentifier, siano progressivi con l'aumentare della versione. in realtà questo succede solo nell'esempio che ho postato, in casi reali i GUID sono completamente randomici.

    se ad esempio uso queste insert

    Delete from Descriptions;
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088365',NULL,'Element A Version1');
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088366','3847fc93-256e-4065-b392-4131b9088365','Element A Version2');
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088317','3847fc93-256e-4065-b392-4131b9088366','Element A Version3');

    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088368',NULL,'Element B Version1');
    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088369','3847fc93-256e-4065-b392-4131b9088368','Element B Version2');

     la riga dove il GUID in bold è l'ultima versione dell'elemento A ma ha il GUID alfabeticamente minore delle precedenti versioni e non ottengo più il risultato aspettato.

    forse il SELECT MAX(CAST(ID AS varchar(36))), dovrebbe restituire l'ID del MAX rownumber?

    Ciao e grazie ancora

     

     

    lunedì 25 ottobre 2010 16:26
  • altra solutzione :

    ;with cte as
    (
    select ID ,ID as PreviousID,1 as [Level]
    from Descriptions where PreviousID is null 
    union all
    select c.ID,F.ID,[Level]+1
    from Descriptions F 
    inner join cte c on c.PreviousID = F.PreviousID 
    )
    select C.ID,
    case
    when C.ID = C.PreviousID then null 
    else C.PreviousID
    end as GrandID
    from cte c 
    inner join (select ID,max(Level) as [Level] from cte group by ID)t on c.ID = t.ID and c.Level = t.Level
    
     

    Best regards
    • Contrassegnato come risposta G Luca martedì 26 ottobre 2010 09:08
    lunedì 25 ottobre 2010 16:53
  • altra solutzione :

    ;with cte as
    
    (
    
    select ID ,ID as PreviousID,1 as [Level]
    
    from Descriptions where PreviousID is null 
    
    union all
    
    select c.ID,F.ID,[Level]+1
    
    from Descriptions F 
    
    inner join cte c on c.PreviousID = F.PreviousID 
    
    )
    
    select C.ID,
    
    case
    
    when C.ID = C.PreviousID then null 
    
    else C.PreviousID
    
    end as GrandID
    
    from cte c 
    
    inner join (select ID,max(Level) as [Level] from cte group by ID)t on c.ID = t.ID and c.Level = t.Level
    
    
     

    Best regards

    ciao,

    anche questa non la padroneggio molto ma qualcosa non mi torna.

    Scritta cosi, mi ritorna sempre in ID l'ID originario(della prima versione) e in GrandID l'ID dell'ultima versione corrispondente(l'informazione che interessa a me) ma se esiste una sola versione, in GrandID ottengo Null.

    Modificandola cosi potrebbe andare ?

     

    with cte as
    (
    select ID ,ID as PreviousID,1 as [Level]
    from Descriptions where PreviousID is null 
    union all
    select c.ID,F.ID,[Level]+1
    from Descriptions F 
    inner join cte c on c.PreviousID = F.PreviousID 
    )
    select C.ID,C.PreviousID as GrandID
    from cte c 
    inner join (select ID,max(Level) as [Level] from cte group by ID)t on c.ID = t.ID and c.Level = t.Level
    

    Cosi in GrandID sembra avere sempre l'ID dell'ultima versione e in ID sempre la prima versione. Se sono uguali esiste solo una versione.

    Sbaglio?

     

    lunedì 25 ottobre 2010 17:11
  • si, è vero !

    Agg. un altra ELEMENT:

    insert into Descriptions(ID,PreviousID,Version) values ('3847fc93-256e-4065-b392-4131b9088370',NULL,'Element C Version1');
    

     

    Result :

    ID                                                                 GrandID

    3847FC93-256E-4065-B392-4131B9088370      3847FC93-256E-4065-B392-4131B9088370
    3847FC93-256E-4065-B392-4131B9088368      3847FC93-256E-4065-B392-4131B9088369
    3847FC93-256E-4065-B392-4131B9088365      3847FC93-256E-4065-B392-4131B9088367


    Best regards
    lunedì 25 ottobre 2010 17:31
  • Quindi la soluzione finale dovrebbe essere

    with cte as
    (
    select ID ,ID as PreviousID,1 as [Level]
    from Descriptions where PreviousID is null 
    union all
    select c.ID,F.ID,c.[Level]+1
    from Descriptions F 
    inner join cte c on c.PreviousID = F.PreviousID 
    ),
     sel_ID as
    (
    select C.PreviousID as ID
    from cte c 
    inner join 
    (select ID,max(Level) as [Level] from cte group by ID)t 
    on c.ID = t.ID and c.Level = t.Level
    )
    select descriptions.* from descriptions inner join sel_ID on descriptions.id=sel_ID.id
    
    sembra funzionare
    • Contrassegnato come risposta G Luca martedì 26 ottobre 2010 09:09
    lunedì 25 ottobre 2010 18:25