【问题标题】:Concatenate Fields in Order - SQL Server按顺序连接字段 - SQL Server
【发布时间】:2016-11-12 02:53:03
【问题描述】:

我有一个由 5 个整数 id 组成的表,并且想添加一个列来获取这些 id,对它们进行排序并以类似于下面的方式连接它们。

id1       id2       id3      id4       id5      new_col
364       53        468      184       469      /53/184/364/468/469/
48        47        49       364       266      /47/48/49/266/364/

有没有一种功能可以让订购变得更快更容易?上帝保佑,如果我必须手动编码排序。

【问题讨论】:

  • 如果您将相同“类型”的数据存储在多个不同的列中,那么您已经失去了关系数据库的意义。 如果数据全部相同,则应将其存储为多行(和单列)。 如果这些列的顺序很重要(1-5 个值),它应该被建模为数据而不是元数据。
  • 行上是否有实际标识符?如果是这样,一个非关键的解决方案将变得容易得多……
  • @BenThul 我怀疑它会更简单。你想到了什么代码?
  • 我比我想出的更喜欢你的 unpivot 解决方案。不过,仍然不是这种数据模型的粉丝。 :)

标签: sql sql-server


【解决方案1】:

你也可以使用XML PATH (Online Demo)

SELECT id1,
       id2,
       id3,
       id4,
       id5,
       new_col = CONCAT('/', ids)
FROM   YourTable
       CROSS APPLY (SELECT CONCAT(id, '/')
                    FROM   (VALUES (id1),
                                   (id2),
                                   (id3),
                                   (id4),
                                   (id5)) V(id)
                    ORDER  BY id
                    FOR XML PATH('')) C(ids) 

【讨论】:

  • 这么棒的伪uppivot!从 mssql2008 开始可用,但这是我第一次看到这个技巧。再次感觉好像我什么都不知道))谢谢!
  • @IvanStarostin 在 2005 年,您可以使用派生表和 UNION ALL 顺便说一句。像这样stackoverflow.com/a/4308905/73226
【解决方案2】:

这对 SQL Server 来说是一个真正的痛点。这是一种方法:

select t.*, v.ids
from t outer apply
     (select ('/' + max(case when seqnum = 1 then id end) +
              '/' + max(case when seqnum = 2 then id end) +
              '/' + max(case when seqnum = 3 then id end) +
              '/' + max(case when seqnum = 4 then id end) +
              '/' + max(case when seqnum = 5 then id end) +
              '/') as ids
      from (select id, row_number() over (order by id) as seqnum
            from (values(id1), (id2), (id3), (id4), (id5)) v(id)
           ) v
     ) v;

【讨论】:

    【解决方案3】:

    我希望真实表中已经有一些id 列。

    declare @data table (c1 int, c2 int, c3 int, c4 int, c5 int)
    
    insert into @data (c1, c2, c3, c4, c5)
    values
    (364, 53, 468, 184, 469),
    (48, 47, 49, 364, 266)
    
    
    ;with NumberedRows as
    (
      select
        d.c1, d.c2, d.c3, d.c4, d.c5, 
        row_number() over(order by (select 1)) rn
      from @data d
    )
    select
      rn, r.c1, r.c2, r.c3, r.c4, r.c5,
      stuff(
        (
          select concat('/', p.num)
          from 
          (
            select rr.c1, rr.c2, rr.c3, rr.c4, rr.c5
            from NumberedRows rr
            where rr.rn = r.rn
          ) rr
          unpivot (num for cols in (c1, c2, c3, c4, c5)) p
          order by p.num
          for xml path(''), type
        ).value('.', 'varchar(max)')
      , 1, 1, '') value_list
    from NumberedRows r
    order by r.rn
    

    看看它与@Martin 和@Gordon 的VALUES (), () 技巧相比有多么复杂。是的。

    【讨论】:

      猜你喜欢
      • 2021-12-10
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 2023-02-10
      相关资源
      最近更新 更多