【问题标题】:Can I order the results of a concatenation in tsql?我可以在 sql 中订购串联的结果吗?
【发布时间】:2010-07-09 19:24:45
【问题描述】:

SQL Server 2008 - 我想将四列连接成分隔值,但我希望它们按字母顺序排列。这可能吗?

**更新:**更多信息... 这将用于每天通过 SSIS 进行的 ETL 作业中大约 700k-1M 行。如果在 SSIS 中有更简单的方法,请告诉我(脚本任务等)。它也可以在存储过程中完成。

还请记住,这些可以为 NULL - 这会给其中一些解决方案带来一些问题。

【问题讨论】:

  • 你如何连接?排序要求您能够在某处的查询中定义 ORDER BY....
  • 只是一个澄清 - 我希望连接的字符串按字母顺序排序,而不是行结果。 IE。基本上切换列顺序。我知道这并不理想并且违反“规则”,但可以帮助解决业务需求并消除我们数据仓库中对多对多维度的需求。
  • 这将应用到多少行?
  • 很多行 - 我会用更多细节更新我的问题。
  • 看起来这些都是正确的,我会将它们都标记为这样,只是想确保我首先有最快的解决方案 - 但仍然会标记为答案(如果可能的话 - 首先这个网站上的问题)。

标签: sql-server tsql sql-server-2008 ssis concatenation


【解决方案1】:

Unpivot 将列分成行,然后对行进行排序。使用任何你喜欢的row string concatenation technique,比如 FOR XML 技巧:

with cte as (
select *
from (values ('A' ,'C', 'B' ,'D')) as T (c1, c2, c3, c4))
select Value + ',' as [*]
from cte
unpivot (Value for c in (c1, c2, c3, c4)) as u
order by Value
for xml path('')

【讨论】:

  • 哇,它使用了我从未听说过的 3 个功能。不错!
  • 不知道如何为我的数据结构安排这个 - 可能工作得很好,但我无法验证。
【解决方案2】:

此要求可能表明您的设计存在问题。如果 4 列中的值在语义上是等效的,您可能会发现将其放入 first normal form 并将重复的列重构到新表中将使此类问题更容易解决。

一个怪物CASE 语句可能会更有效率,但这里有一种方法没有

WITH t AS
(
SELECT 1 as rowid, 'cat' as C1, 'apple' As C2, 
      'bear' AS C3, 'fox' AS C4 UNION ALL
SELECT 2 as rowid, 'B' as C1, 'D' As C2, 'E' AS C3, 'G' AS C4 
)

SELECT rowid,   STUFF((SELECT ',' + C FROM 
(
SELECT C1 AS C FROM t t2 WHERE  t.rowId = t2.rowId
UNION ALL
SELECT C2 AS C FROM t t2 WHERE  t.rowId = t2.rowId
UNION ALL
SELECT C3 AS C FROM t t2 WHERE  t.rowId = t2.rowId
UNION ALL
SELECT C4 AS C FROM t t2 WHERE  t.rowId = t2.rowId
) D
ORDER BY C
        FOR XML PATH('')),1,1,'') X

给予

rowid       X
1           apple,bear,cat,fox
2           B,D,E,G

【讨论】:

  • 这行得通,我刚刚在这里找到了与此类似的解决方案。我正在寻找表现最好的人,所以我将不得不尝试其他解决方案并看看。然而,这确实回答了这个问题(一旦我测试了一些,我会标记所有正确的项目)。
【解决方案3】:

很复杂,但这会奏效:

   Select Case 
         When a>b And a>c And a>d Then a + ',' +
             Case When b>c And b>d Then b + ',' +
                      Case When c>d Then c Else d End 
                  When c>b And c>d Then c + ',' +
                      Case When b>d Then b Else d End 
                  When d>b And d>c Then d + ',' +
                      Case When b>c Then b Else c End End +
         When b>a And b>c And b>d Then b + ',' +
             Case When a>c And a>d Then a + ',' +
                      Case When c>d Then c Else d End 
                  When c>a And c>d Then c + ',' +
                      Case When a>d Then a Else d End 
                  When d>a And d>c Then a + ',' +
                      Case When a>c Then a Else c End End + ',' +
          etc... 
    End

但我会在代码中而不是在数据库中执行此操作...

编辑:(作为计算列):

  Alter Table MyTable Add Column SortedABCD As
        Case 
             When a>b And a>c And a>d Then a + ',' +
                 Case When b>c And b>d Then b + ',' +
                          Case When c>d Then c Else d End 
                      When c>b And c>d Then c + ',' +
                          Case When b>d Then b Else d End 
                      When d>b And d>c Then d + ',' +
                          Case When b>c Then b Else c End End +
             When b>a And b>c And b>d Then b + ',' +
                 Case When a>c And a>d Then a + ',' +
                          Case When c>d Then c Else d End 
                      When c>a And c>d Then c + ',' +
                          Case When a>d Then a Else d End 
                      When d>a And d>c Then a + ',' +
                          Case When a>c Then a Else c End End + ',' +
              etc... 
        End

【讨论】:

  • 虽然如果他使用持久计算列,在 T-SQL 中完成命中可能不是不合理的?
  • 是的,没错,那么唯一的打击就是插入或更新行时......但我认为这不会对性能造成重大影响......这只是一个维护问题因为它又长又麻烦......如果你必须添加另一列怎么办?还是第六个??有 4 列,您需要 4 Factorial = 24 case 语句。第五列需要 120,而第六列是不可能的。
  • @Cruachan - 我不熟悉计算列,所以我查找了它们 - 看起来很完美,但似乎不起作用。可能适用于案例陈述,但它太大了,让我头疼,所以我可能会在星期一回来。使用我当前的解决方案,我在 create table 语句中的计算列出现此错误:“在此上下文中不允许子查询。只允许标量表达式。”
  • @Charles Bretana - 由于标准行业法规,它是 4,而且只有 4。能改变吗?是的。但是可能性很小。
  • @elgabito,听起来您的计算列定义中仍然有关键字Select...删除它...它应该可以工作...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多