在DataSet中合并多个行和列数据

时间:2019-06-28 06:50:19

标签: c# asp.net sql-server datatable dataset

我的数据集如下:

enter image description here

其中B1,B2,C1,C2和C3是列名。 G1,G2,S1和T1是我的数据集中的第一行元素。

现在我想将相似的列/行组合到Group中。 示例:列B1,B2和B3合并为单个组B, 行:G1和G2合并在一起形成一个单行G。 下面是我需要的O / P数据集。

enter image description here

我尝试使用Dictionary和DataSet Loops,但无法获取此O / P。

有人可以帮我吗?

2 个答案:

答案 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;

db<>fiddle

答案 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)