Sql server 2008 从表中创建分层格式的输出
我有这样一个SQL表:Sql server 2008 从表中创建分层格式的输出,sql-server-2008,tsql,hierarchical,Sql Server 2008,Tsql,Hierarchical,我有这样一个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 2
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
我想要这样的输出:
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代码实现这一点
对于每个始终具有相似Descr值的相似CC值,它会在输出部分中写入的序列中显示与该特定CC值相关的所有C_No、Vol和Wt值。在tsql代码中不能这样做。您需要在应用程序代码中执行此类操作 我不会这么做。TSQL用于获取数据,然后使用应用程序代码格式化数据。
但是,如果您在Query analyzer中工作,并且只希望输出在那里,则可以尝试以下操作:
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;
或者你可以使用一组。。。使用ROLLUP和CASE,可以在单个查询中获得结果
下面是一个使用破折号而不是空格来确保格式可见的示例:
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
按层次顺序表示数据的最佳方法之一是使用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
我得到以下结果(以上述语句返回的一行形式):
这就像一个魔咒,在Microsoft SQL Server Management Studio 2012上进行了测试。试试这个
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+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(或任何数据库)不是其他人所谈论的格式化的地方。请查看这个问题。
你的问题措辞很好,但我建议你考虑用不同的语言来做。TSQL不以其格式著称。同意这一点,你最好在你的C#代码中这样做,所以没有其他方法可以使用光标?也许你可以回答为什么要在TSQL中这样做的问题?你不应该这样做是TSQL,但这是可能的。(No column name)
2050
Des1
123
20
40
125
20
40
126
20
40
2060
Des2
123
30
50
125
30
50