比较逗号分隔的行

时间:2013-09-03 06:19:51

标签: sql sql-server tsql sql-server-2000

我有一个要求,我应该将顶行与以逗号分隔的前一行数据库记录进行比较。 例如: 我的表格数据如下所示:

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

我必须显示相位中最新更改的内容以及更新后的内容。逗号分隔数据在前端提交了多个chechbox。用户可以通过同一页面中的多个复选框更新它们。 这里Test3是最近的变化,然后低于Test2是最近的变化,第三行是实际的第一次变化。

我需要将结果显示为

      Phase        Updated By
      Test3        sxmalla
      Test2        rkgauta
      Test1,Test3  sxmalla

以下是我目前用于比较2个逗号分隔行的代码

  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 p1.project_id=@Project_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 p1.project_id=@Project_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 @i=@i+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 个答案:

答案 0 :(得分:0)

这是一个可能的解决方案:

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

这是使用SQLServerCentral中的DelimitedSplit8K功能进行拆分,但我相信您可以使用现有功能。

<强> SQLFiddle DEMO

答案 1 :(得分:0)

我将尝试回答规范化问题。

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

这会在单独的行上显示结果(无逗号)

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)