2013-09-03 3 views
0

J'ai une exigence où je devrais comparer la rangée supérieure avec les rangées précédentes d'enregistrements de base de données dont ils sont séparés par des virgules. exemple: Mes données de table ressemble à ceci:Comparer les lignes séparées par des virgules

 ID Phase    Updated By 
     1 Test1,Test2,Test3 sxmalla 
     2 Test1,Test2   rkgauta 
     3 Test1,Test3   sxmalla 

Je dois afficher Somthing les plus récents changements de phase et qui a updated.The données par des virgules seperated est soumis à plusieurs chechboxes en fin avant. L'utilisateur peut les mettre à jour via plusieurs cases à cocher dans la même page. Ici Test3 est le changement le plus récent, puis en dessous Test2 est le changement le plus récent et sur la troisième ligne la première entrée réelle.

-je présenter le résultat comme

 Phase  Updated By 
     Test3  sxmalla 
     Test2  rkgauta 
     Test1,Test3 sxmalla 

Voici le code que j'utilise actuellement pour comparer deux virgule lignes seperated

ALTER Proc [dbo].[PMT_GetPhasesEditHistory] 

    @Project_ID int 
    As Begin 
    SET NOCOUNT ON 
    Declare @added varchar(1000), @removed varchar(1000),@strN varchar(1000),@strO varchar(1000) 
    DECLARE test_cursor CURSOR FOR          


    SET @strO=(SELECT TOP 1 P1.Phase from phase P1,Phase P2 where P1.ID = P2.ID-1 and [email protected]_ID order by p1.ID Desc) 

    SET @strN =(SELECT TOP 1 P2.Phase from phase P1,Phase P2 
    where P1.ID = P2.ID-1 and [email protected]_ID order by p1.ID Desc) 

    If object_id('dbo.#tN') is not null Begin ; drop table dbo.#tN ;End   

    CREATE TABLE dbo.#tN(var varchar(100)); insert into #tN select * from fnSplitStringAsTable(@strN,',') 

    If object_id('dbo.#tO') is not null Begin; drop table dbo.#tO ;End   

    CREATE TABLE dbo.#tO (var varchar(100)); insert into #tO select * from fnSplitStringAsTable(@strO,',') 

    Declare @i int 
    Set @i=1 
    Set @added = '' 
    While @i != (select COUNT(*)+1 from #tN) 
    Begin 
    if not exists(select VAR from #tO where var = (select Top 1 var from #tN where var in (Select Top (@i) VAR from #tN where Var in (Select Top (@i) var From #tN order by VAR desc) order by var asc))) 
    Begin 
    Set @added = @added + (select Top 1 var from #tN where var in (Select Top (@i) VAR from #tN where Var in (Select Top (@i) var From #tN order by VAR desc) order by var asc)) + ',' 
    End 
    set @[email protected]+1 
    End 

    If(len(@added) > 1) Begin; set @added = RTRIM(LEFT(@added,Len(@added) - 1)); End 
    Select @added as Added 

    drop table #tN;Drop table #tO 
    End 
+2

s'il vous plaît considérer normaliser vos données en premier. divisez vos données séparées par des virgules en colonne réelle et probablement une autre table – mvp

+1

Donc, généralement, vous devez comparer la dernière ligne (3) avec la ligne précédente (2) et extraire ce que "nouveau" a été ajouté dans la ligne (2) . Puis comparer la rangée (2) avec la rangée (1) et vérifier à nouveau ce que "nouveau" a été ajouté dans la rangée (1)? c'est ce que tu veux? – gotqn

+0

alors pouvez-vous suggérer comment puis-je faire cela @MVP ?? – user1894745

Répondre

0

Voici une solution possible:

WITH CTE_Prep AS 
(
    SELECT *, DENSE_RANK() OVER (ORDER BY ID DESC) RN 
    FROM phase 
    CROSS APPLY dbo.DelimitedSplit8K(Phase,',') 
) 
,CTE_Result AS 
(
    SELECT ID, STUFF ((SELECT ', ' +Item 
         FROM CTE_Prep c WHERE Item NOT IN (SELECT Item FROM CTE_Prep c2 WHERE c2.RN + 1 = c.RN) 
         AND c.Id = c3.ID 
         FOR XML PATH('')),1,2,'') AS Phase 
    FROM CTE_Prep c3 
    GROUP BY ID 
) 
SELECT r.Phase, p.[Updated By] FROM CTE_Result r 
LEFT JOIN phase p ON r.id = p.id 

Ceci utilise la fonction DelimitedSplit8K de SQLServerCentral pour le fractionnement, mais je suis s Vous pouvez faire avec votre existant.

SQLFiddle DEMO

+0

J'utilise sql 2000 production.Je pense que cela ne fonctionnera pas pour sql 2000 :-( – user1894745

+0

Non ce ne sera pas.Vous auriez dû mentionner cette "petite" chose au début :) –

+0

Oui, je devrais avoir, pouvons-nous avoir toutes les autres solutions pour cela @Nanad Zivkovic – user1894745

0

Je vais essayer de répondre à la question de la normalisation.

Table PhaseTest 
PhaseID int 
TestID int 
PK PhaseID, TestID 
(this PK will enforce no duplicate TestID in a PhaseID 

Table PhaseUser 
PhaseID int PK 
UserID int 

Table Test 
TestID int PK 
TestName varchar 

Table User 
UserID int PK 
UserName varchar 

cela montre les résultats sur des lignes séparées (pas de virgule)

select PT1.PhaseID, Test.TestName, User.UserName 
    from PhaseTest PT1 
    left outer join PhaseTest PT2 
    on PT2.PhaseID = PT1.PhaseID + 1 
    and PT2.TestID = PT1.TestID 
    join PhaseUser 
    on PhaseUser.UserID = PT1.UserID 
    join Test 
    on Test.TestID = PT1.UserID 
where PT2.PhaseID is null 
order by PT1.TestID 
union 
select PT1.PhaseID, Test.TestName, User.UserName 
    from PhaseTest PT1 
    join PhaseUser 
    on PhaseUser.UserID = PT1.UserID 
    join Test 
    on Test.TestID = PT1.UserID 
where PT1.PhaseID = (select max(PhaseID) from PhaseTest) 
Questions connexes