Объединить несколько строк и столбцов данных в DataSet - PullRequest
0 голосов
/ 28 июня 2019

У меня есть DataSet, как показано ниже:

enter image description here

Где B1, B2 C1, C2 и C3 - имена столбцов.G1, G2, S1 и T1 являются первыми элементами строк в моем наборе данных.

Теперь я хочу объединить похожие столбцы / пути в группу.Пример: столбцы B1, B2 и B3 объединяются в одну группу B, строки: G1 и G2 объединяются в одну строку G. Ниже приведен необходимый набор данных O / P.

enter image description here

Я пытался использовать словари и циклы DataSet, используя, но не могу получить это O / P.

Может кто-нибудь помочь мне с этим.

1 Ответ

2 голосов
/ 28 июня 2019

Это должно быть динамичным, добавляет огромную сложность этому решению.Поскольку вы не ответили на вопрос о версии, я не использовал 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;

дБ <> скрипка

...