【问题标题】:Combine multiple rows and columns data in DataSet合并DataSet中的多行多列数据
【发布时间】:2019-11-10 03:11:35
【问题描述】:

我有一个如下所示的数据集:

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

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

我尝试使用字典和数据集循环,但无法获得此 O/P。

谁能帮帮我。

【问题讨论】:

  • 名为B的列数是静态的吗?
  • 列数可能因B而异,如B1、B2、B3和B4..等等
  • 那些语句冲突;它们是静态的还是变化的?他们不能两者兼而有之。
  • 他们会有所不同..@Larnu
  • 什么 SQL Server 版本?

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


【解决方案1】:

这必须是动态的,这给这个解决方案增加了巨大的复杂性。由于您没有回答版本问题,我没有使用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 的人来说,这是一个陡峭的学习曲线:

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

【讨论】:

    【解决方案2】:

    您可以应用以下逻辑从 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) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多