SQL SELECT:带有换行符和每组标题的连续列

时间:2016-10-14 13:56:20

标签: sql sql-server grouping sqlxml for-xml-path

我从SQL查询得到以下SELECT结果:

ID | category| value | desc
1  | A       | 10    | text1
2  | A       | 11    | text11
3  | B       | 20    | text20
4  | B       | 21    | text21
5  | C       | 30    | text30

此结果存储在名为#temptab的临时表中。然后,这个临时表在另一个SELECT中用于通过字符串连接建立一个新的列(不要问我这背后的详细原理。这是我从同事那里得到的代码)。通过FOR XML PATH(),此列的输出是结果列表,然后用于向客户发送邮件。

第二个SELECT如下所示:

SELECT t1.column,
       t2.column,
       (SELECT t.category + ' | ' + t.value + ' | ' + t.desc + CHAR(9) + CHAR(13) + CHAR(10)
           FROM #temptab t
           WHERE t.ID = ttab.ID
           FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)') AS colname
FROM table1 t1
...
INNER JOIN #temptab ttab on ttab.ID = someOtherTable.ID
...

不想过多细节,列colname会填充多个条目(由于多个匹配),因此,此列中存储了一个更长的字符串(CHAR(9) + CHAR(13) + CHAR(10)本质上是越线)。 colname的结果/内容如下所示(用于向客户发送邮件):

A | 10 | text1
A | 11 | text11
B | 20 | text20
B | 21 | text21
C | 30 | text30

现在我想知道,如果有一种方法可以更好地格式化这个输出字符串。最好的情况是将相同的类别组合在一起,并在不同类别之间添加标题和空行:

*A*
A | 10 | text1
A | 11 | text11

*B*
B | 20 | text20
B | 21 | text21

*C*
C | 30 | text30

我的问题是:如何修改上述查询(特别是字符串连接部分)以实现上述格式?我正在考虑使用GROUP BY语句,但这显然不会产生预期的结果。

修改:我使用Microsoft SQL Server 2008 R2 (SP2) - 10.50.4270.0 (X64)

2 个答案:

答案 0 :(得分:1)

Declare @YourTable table (ID int,category varchar(50),value int, [desc] varchar(50))
Insert Into @YourTable values
(1,'A',10,'text1'),
(2,'A',11,'text11'),
(3,'B',20,'text20'),
(4,'B',21,'text21'),
(5,'C',30,'text30')

Declare @String  varchar(max) = '' 

Select @String = @String + Case when RowNr=1 Then Replicate(char(13)+char(10),2) +'*'+Category+'*' Else '' end 
                         + char(13)+char(10) + category + ' | ' + cast(value as varchar(25)) + ' | ' + [desc] 
 From (
        Select * 
              ,RowNr=Row_Number() over (Partition By Category Order By Value)
         From  @YourTable

      ) A Order By Category, Value

Select Substring(@String,5,Len(@String))

返回

*A*
A | 10 | text1
A | 11 | text11

*B*
B | 20 | text20
B | 21 | text21

*C*
C | 30 | text30

答案 1 :(得分:0)

这应该返回你想要的东西

Thread

结果

Declare @YourTable table (ID int,category varchar(50),value int, [desc] varchar(50))
Insert Into @YourTable values
(1,'A',10,'text1'),
(2,'A',11,'text11'),
(3,'B',20,'text20'),
(4,'B',21,'text21'),
(5,'C',30,'text30');

WITH Categories AS
(
    SELECT category
          ,'**' + category + '**' AS CatCaption
          ,ROW_NUMBER() OVER(ORDER BY category) AS CatRank
    FROM @YourTable
    GROUP BY category
)
,Grouped AS
(
    SELECT c.CatRank
          ,0 AS ValRank
          ,c.CatCaption AS category
          ,-1 AS ID
          ,'' AS Value
          ,'' AS [desc]
    FROM Categories AS c

    UNION ALL

    SELECT c.CatRank
          ,ROW_NUMBER() OVER(PARTITION BY t.category ORDER BY t.Value)
          ,t.category
          ,t.ID
          ,CAST(t.value AS VARCHAR(100))
          ,t.[desc] 
    FROM @YourTable AS t
    INNER JOIN Categories AS c ON t.category=c.category
)
SELECT category,Value,[desc]
FROM Grouped 
ORDER BY CatRank,ValRank