我有一个这样的SQL表:
CC Descr C_NO Vol Wt
2050 Des1 123 20 40
2060 Des2 123 30 50
2050 Des1 125 20 40
2060 Des2 125 30 50
2050 Des1 126 20 40
我希望输出如下:
2050
Des1
123
20
40
125
20
40
126
20
40
2060
Des2
123
30
50
125
30
50
如何使用TSQL代码执行此操作?
对于始终具有相似描述值的每个类似CC值,它显示与输出部分中写入的序列中的特定CC值相关的所有C_No,Vol和Wt值。
答案 0 :(得分:2)
试试这个
DECLARE @t TABLE
(
CC BIGINT,
Descr NVARCHAR(10),
C_NO INT,
Vol SMALLINT,
WT SMALLINT
)
INSERT INTO @t(CC,Descr,C_NO,Vol,WT)
VALUES (2050,'Des1',123,20,40)
,(2060,'Des2',123,30,50)
,(2050,'Des1',125,20,40)
,(2060,'Des2',125,30,50)
,(2050,'Des1',126,20,40)
;WITH CTE1 AS(
SELECT
t1.CC
,t1.Descr
,MergedColumn = STUFF(
(SELECT
','
+ CAST(C_NO AS VARCHAR(10)) + '/' + CAST(Vol AS VARCHAR(10)) + '/' + CAST(Wt AS VARCHAR(10))
FROM @t AS t2
WHERE t2.CC=t1.CC AND t2.Descr=t2.Descr
FOR XML PATH('')),1,1,'')
FROM @t t1
GROUP BY t1.CC,t1.Descr)
,CTE2 AS
(
SELECT
X.CC
,X.Descr
,Y.SplitDataByComma
FROM
(
SELECT
*,
CAST('<X>'+REPLACE(F.MergedColumn,',','</X><X>')+'</X>' AS XML) AS xmlfilter
FROM CTE1 F
)X
CROSS APPLY
(
SELECT fdata.D.value('.','varchar(50)') AS SplitDataByComma
FROM X.xmlfilter.nodes('X') AS fdata(D)
)Y
)
,CTE3 AS
(
SELECT
X.CC
,X.Descr
,Y.SplitDataBySlash
, X.SplitDataByComma AS GrpID
,ROW_NUMBER() OVER( PARTITION BY X.SplitDataByComma ORDER BY X.CC,X.Descr ) AS Rn
,X.SplitDataByComma + CAST(CC AS Varchar(200)) + CAST(Descr AS Varchar(200)) CC_Descr
FROM
(
SELECT
*,
CAST('<X>'+REPLACE(F.SplitDataByComma,'/','</X><X>')+'</X>' AS XML) AS xmlfilter
FROM CTE2 F
)X
CROSS APPLY
(
SELECT fdata.D.value('.','varchar(50)') AS SplitDataBySlash
FROM X.xmlfilter.nodes('X') AS fdata(D)
)Y
)
,CTE4 AS
(
SELECT
Rn = ROW_NUMBER() OVER(PARTITION BY CC ORDER BY CC)
,CC
,Descr
,CASE WHEN Rn = 1 THEN CAST (SplitDataBySlash AS VARCHAR(10)) ELSE ' ' END C_NO
,CASE WHEN Rn = 1 THEN ' ' ELSE CAST (SplitDataBySlash AS VARCHAR(10)) END Vol_Wt
,GrpID
FROM Cte3
)
,CTE5 AS(
SELECT
CC = CASE WHEN Rn > 1 THEN ' ' ELSE CAST(CC AS Varchar(200)) END
,Descr = CASE WHEN Rn > 1 THEN ' ' ELSE CAST(Descr AS Varchar(200)) END
,C_NO
,Vol_Wt
,GrpID
FROM Cte4)
SELECT
CHAR(10)
+ REPLICATE(SPACE(1),10)
+ CAST(CC as VARCHAR(100))
+ CHAR(10)
+ REPLICATE(SPACE(1),15)
+ Descr
+ CHAR(10)
+ REPLICATE(SPACE(1),10)
+ C_NO
+ CHAR(10)
+ REPLICATE(SPACE(1),15)
+ Vol_Wt
FROM CTE5
在文本模式(CTRL + T)中,结果为
2050
Des1
123
20
40
125
20
40
126
20
40
2060
Des2
123
30
50
125
30
50
在网格模式(CTRL + D)中,结果为
(No column name)
2050
Des1
123
20
40
125
20
40
126
20
40
2060
Des2
123
30
50
125
30
50
但是,SQL Server(或任何数据库)不像其他人所说的那样进行格式化。请调查此事。
答案 1 :(得分:1)
我不会这样做。 TSQL用于获取数据,然后使用应用程序代码格式化该数据 但是如果你在Query分析器中工作并且只想在那里输出,你可以尝试以下方法:
DECLARE mytable_cursor CURSOR FOR
SELECT CC, Descr, C_NO, Vol, Wt
FROM myTable
ORDER BY CC, Descr, C_NO
OPEN mytable_cursor;
FETCH NEXT FROM mytable_cursor
INTO @CC, @Descr, @C_NO, @Vol, @Wt
SET @oCC = @CC
SET @oDescr = @Descr
SET @oC_NO = @C_NO
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @CC;
WHILE @@FETCH_STATUS = 0 AND @oCC = @CC
BEGIN
PRINT ' ' + @Descr;
WHILE @@FETCH_STATUS = 0 AND @oDescr = @Descr
BEGIN
PRINT ' ' + @C_NO;
WHILE @@FETCH_STATUS = 0 AND @oC_NO = @C_NO
BEGIN
PRINT ' ' + @Vol;
PRINT ' ' + @WT;
FETCH NEXT FROM mytable_cursor
INTO @CC, @Descr, @C_NO, @Vol, @Wt
END
SET @oC_NO = @C_NO
END
SET @oDescr = @Descr
END
SET @oCC = @CC
END
CLOSE mytable_cursor;
DEALLOCATE mytable_cursor;
或者你可以使用GROUP BY ... WITH ROLLUP和CASE WHEN来获得单个查询的结果。
这是一个使用破折号而不是空格的示例,以确保格式可见:
SELECT (CASE
WHEN Descr IS NULL THEN CC
WHEN C_NO IS NULL THEN '----' + Descr
WHEN Vol IS NULL THEN '--' + C_NO
WHEN Wt IS NULL THEN '------' + Vol
ELSE '------' + Wt
END)
FROM
(SELECT CC, Descr, C_NO, Vol, Wt
FROM my
GROUP BY CC, Descr, C_NO, Vol, Wt
WITH ROLLUP) AS x
WHERE CC IS NOT NULL
ORDER BY CC, Descr, C_NO, Vol, Wt
答案 2 :(得分:0)
你不能在tsql代码中这样做。您需要在应用程序代码中执行此类操作。
答案 3 :(得分:0)
以层次结构顺序表示数据的最佳方法之一是使用XML。更多的东西,通常使用XML与卓越的性能相关联。
使用您的示例信息和代码的和平:
;WITH DistinctValues (CC,Descr ) AS
(
SELECT DISTINCT CC,Descr
FROM @TableOne
)
SELECT (
SELECT CC AS "CC/@CC"
,Descr AS "CC/Descr"
,(
SELECT C_NO AS "C_NO/@C_NO",
Vol AS "C_NO/Vol",
Wt AS "C_NO/Wt"
FROM @TableOne AS Data
WHERE Data.CC=DV.CC AND Data.Descr=DV.Descr
FOR XML PATH(''),TYPE
) AS "CC"
FROM DistinctValues AS DV
FOR XML PATH(''),TYPE
)
FOR XML PATH('Source'),TYPE
我得到以下结果(以上面的语句返回一行的形式):
<Source>
<CC CC="2050">
<Descr>Des1</Descr>
<C_NO C_NO="123">
<Vol>20</Vol>
<Wt>40</Wt>
</C_NO>
<C_NO C_NO="125">
<Vol>20</Vol>
<Wt>40</Wt>
</C_NO>
<C_NO C_NO="126">
<Vol>20</Vol>
<Wt>40</Wt>
</C_NO>
</CC>
<CC CC="2060">
<Descr>Des2</Descr>
<C_NO C_NO="123">
<Vol>30</Vol>
<Wt>50</Wt>
</C_NO>
<C_NO C_NO="125">
<Vol>30</Vol>
<Wt>50</Wt>
</C_NO>
</CC>
</Source>
请注意,T-SQL中的XML函数结合XML语言结构为您提供了大量可能的输出数据格式变体 - 您使用一个或多个节点,您可以将数据表示为属性或节点文本。根据需要将其组合在一起,因为您觉得在应用程序级别中最容易使用它。
以下是我用来生成以前的XML结构的整个代码(只是复制和粘贴):
DECLARE @TableOne TABLE
(
CC BIGINT,
Descr NVARCHAR(10),
C_NO INT,
Vol SMALLINT,
WT SMALLINT
)
INSERT INTO @TableOne(CC,Descr,C_NO,Vol,WT)
VALUES (2050,'Des1',123,20,40)
,(2060,'Des2',123,30,50)
,(2050,'Des1',125,20,40)
,(2060,'Des2',125,30,50)
,(2050,'Des1',126,20,40)
;WITH DistinctValues (CC,Descr ) AS
(
SELECT DISTINCT CC,Descr
FROM @TableOne
)
SELECT (
SELECT CC AS "CC/@CC"
,Descr AS "CC/Descr"
,(
SELECT C_NO AS "C_NO/@C_NO",
Vol AS "C_NO/Vol",
Wt AS "C_NO/Wt"
FROM @TableOne AS Data
WHERE Data.CC=DV.CC AND Data.Descr=DV.Descr
FOR XML PATH(''),TYPE
) AS "CC"
FROM DistinctValues AS DV
FOR XML PATH(''),TYPE
)
FOR XML PATH('Source'),TYPE
这就像一个魅力,它在Microsoft SQL Server Management Studio 2012上进行了测试。