我的数据集如下:
其中B1,B2,C1,C2和C3是列名。 G1,G2,S1和T1是我的数据集中的第一行元素。
现在我想将相似的列/行组合到Group中。 示例:列B1,B2和B3合并为单个组B, 行:G1和G2合并在一起形成一个单行G。 下面是我需要的O / P数据集。
我尝试使用Dictionary和DataSet Loops,但无法获取此O / P。
有人可以帮我吗?
答案 0 :(得分:2)
必须动态,这为该解决方案增加了大量的复杂性。由于您尚未回答版本问题,因此我没有使用STRING_AGG
,但是,如果您使用的是SQL Server 2017+,则可以简化查询的使用。
首先,一些示例数据:
CREATE TABLE dbo.Matrix ([Data] char(2),
B1 tinyint,
B2 tinyint,
C1 tinyint,
C2 tinyint,
C3 tinyint)
INSERT INTO dbo.Matrix ([Data],
B1,
B2,
C1,
C2,
C3)
VALUES('G1',1,1,2,2,4),
('G2',1,1,1,1,1),
('S1',2,1,2,1,1),
('T1',1,3,2,2,3);
GO
现在,如果不是动态的,则可以使用“交叉”选项卡将数据分为几组,如下所示:
SELECT LEFT(M.[Data],1) AS [Data],
SUM(CASE V.Col WHEN 'B' THEN V.ColVal END) AS B,
SUM(CASE V.Col WHEN 'C' THEN V.ColVal END) AS C
FROM dbo.Matrix M
CROSS APPLY(VALUES('B',M.B1),
('B',M.B2),
('C',M.C1),
('C',M.C2),
('C',M.C3))V(Col,ColVal)
GROUP BY LEFT(M.[Data],1);
不幸的是,由于它是动态的,因此我们需要动态SQL。老实说,这不是开始,我不是在这里支持此SQL。您需要了解它,维护它,支持它,并(因为它是动态SQL)(<动态> 是动态SQL)使其保持安全。我很高兴回答有关如何工作的一些问题,但是对于不熟悉SQL的人来说,这是一个艰难的学习过程:
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SELECT LEFT(M.[Data],1) AS [Data],' + NCHAR(13) + NCHAR(10) +
STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
N' SUM(CASE V.Col WHEN N' + QUOTENAME(LEFT(C.COLUMN_NAME,1),'''') + N' THEN V.ColVal END) AS ' + QUOTENAME(LEFT(C.COLUMN_NAME,1))
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_SCHEMA = N'dbo'
AND C.TABLE_NAME = N'Matrix'
AND C.COLUMN_NAME != N'Data' --Assumes that all other columns are applicable
GROUP BY LEFT(C.COLUMN_NAME,1)
ORDER BY LEFT(C.COLUMN_NAME,1)
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,3,N'') + NCHAR(13) + NCHAR(10) +
N'FROM dbo.Matrix M' + NCHAR(13) + NCHAR(10) +
N' CROSS APPLY(VALUES' + STUFF((SELECT ',' + NCHAR(13) + NCHAR(10) +
N' (N' + QUOTENAME(LEFT(C.COLUMN_NAME,1),'''') + N',M.' + QUOTENAME(C.COLUMN_NAME) + N')'
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_SCHEMA = N'dbo'
AND C.TABLE_NAME = N'Matrix'
AND C.COLUMN_NAME != N'Data' --Assumes that all other columns are applicable
ORDER BY C.COLUMN_NAME
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,26,N'') + N')V(Col,ColVal)' + NCHAR(13) + NCHAR(10) +
N'GROUP BY LEFT(M.[Data],1)' + NCHAR(13) + NCHAR(10) +
N'ORDER BY LEFT(M.[Data],1);';
PRINT @SQL; --Your debugging best friend.
EXEC sp_executesql @SQL;
答案 1 :(得分:0)
您可以应用以下逻辑从SQL Server获得所需的输出:
create table T_DataSet
(
Data varchar(50),
B1 int,
B2 int,
C1 int,
C2 int,
C3 int
)
INSERT INTO T_DataSet ([Data],B1,B2,C1,C2,C3)
VALUES('G1',1,1,2,2,4),
('G2',1,1,1,1,1),
('S1',2,1,2,1,1),
('T1',1,3,2,2,3);
DECLARE @QUERY VARCHAR(MAX)=''
DECLARE @Columns VARCHAR(MAX)=''
;with tbl_COLUMN_NAME (COLUMN_NAME) AS
(
select name as COLUMN_NAME from sys.all_columns
where object_id = (select object_id from sys.tables where name = 'T_DataSet')
and name <> 'Data'
)
SELECT
@Columns = ISNULL(@Columns +',', '') + T.COLUMN_NAME
FROM
(
select
COLUMN_NAME = 'SUM(' +
(select SUBSTRING(
(
SELECT '+'+ COLUMN_NAME
FROM tbl_COLUMN_NAME
where LEFT(COLUMN_NAME,1) = LEFT(inner_C1.COLUMN_NAME,1)
FOR XML PATH('')
), 2 , 9999))
+ ') AS ' + LEFT(COLUMN_NAME,1)
from tbl_COLUMN_NAME as inner_C1
Group by LEFT(COLUMN_NAME,1)
)T
set @QUERY = 'select LEFT([Data],1) as Data ' + @Columns + '
From T_DataSet
Group by LEFT([Data],1)';
PRINT @QUERY
EXEC(@QUERY)