Select and merge rows in a table in SQL Stored procedure

前端 未结 3 1323
梦毁少年i
梦毁少年i 2021-01-28 01:40

Have a temp table with schema: ID | SeqNo | Name

ID - Not unique
SeqNo - Int (can be 1,2 or 3). Sort of ID+SeqNo as Primary key
Name - Any text

And sam

相关标签:
3条回答
  • 2021-01-28 01:51

    If SeqNo is limited to 1,2,3:

    select id, a.name + coalesce('/'+b.name, '') + coalesce('/'+c.name, '')
    from myTable a
    left outer join myTable b on a.id=b.id and b.seqno = 2
    left outer join myTable c on a.id=c.id and c.seqno = 3
    where a.seqno = 1;
    

    If SeqNo is open ended you can deploy a recursive cte:

    ;with anchor as (
       select id, name, seqno
          from myTable
          where seqno=1)
    , recursive as (
       select id, name, seqno
          from anchor
          union all
       select t.id, r.name + '/' + t.name, t.seqno
          from myTable t
          join recursive  r on t.id = r.id and r.seqno+1 = t.seqno)
    select id, name from recursive;
    
    0 讨论(0)
  • 2021-01-28 02:04

    The solution is good. I have a similar issue, but here I am using 2 different tables. ex:

    table1 
    
    1 | 1 |
    2 | 3 |
    3 | 1 |
    4 | 2 |
    5 | 1 |
    1 | 2 |
    1 | 3 | 
    4 | 1 |
    5 | 2 |
    2 | 2 |
    4 | 3 |
    
    table2 
    1 | RecordA
    2 | RecordB
    3 | RecordC
    

    I want to get the data from two tables and display in the below format.

    1 | RecordA,RecordB,RecordC|
    2 | RecordB,RecordC|
    3 | RecordA |
    4 | RecordA,RecordB,RecordC|
    5 | RecordA,RecordB | 
    
    0 讨论(0)
  • 2021-01-28 02:14

    If you know SeqNo will never be more than 3:

    select Id, Names = stuff(
        max(case when SeqNo = 1 then '/'+Name else '' end)
      + max(case when SeqNo = 2 then '/'+Name else '' end)
      + max(case when SeqNo = 3 then '/'+Name else '' end)
      , 1, 1, '')
    from table1 
    group by Id
    

    Otherwise, something like this is the generic solution to an arbitrary number of items:

    select Id, Names = stuff((
      select '/'+Name from table1 b
      where a.Id = b.Id order by SeqNo
      for xml path (''))
      , 1, 1, '')
    from table1 a
    group by Id
    

    Or write a CLR UDA.

    Edit: had the wrong alias on the correlated table!

    Edit2: another version, based on Remus's recursion example. I couldn't think of any way to select only the last recursion per Id, without aggregation or sorting. Anybody know?

    ;with
      myTable as (
        select * from (
          values 
            (1, 1, 'RecordA')  
          , (2, 1, 'RecordB')  
          , (3, 1, 'RecordC')  
          , (1, 2, 'RecordD')  
          , (4, 1, 'RecordE')  
          , (5, 1, 'RecordF')  
          , (3, 2, 'RecordG')
          ) a (Id, SeqNo, Name)
        )    
    , anchor as (
        select id, name = convert(varchar(max),name), seqno
        from myTable where seqno=1
        )
    , recursive as (
        select id, name, seqno
        from anchor
        union all
        select t.id, r.name + '/' + t.name, t.seqno
        from myTable t
        join recursive  r on t.id = r.id and r.seqno+1 = t.seqno
        )
    select id, name = max(name) 
    from recursive
    group by id;
    ---- without aggregation, we get 7 rows:
    --select id, name
    --from recursive;
    
    0 讨论(0)
提交回复
热议问题