Кросс-таблица панд в SQL - PullRequest
1 голос
/ 29 апреля 2019

Я борюсь с реализацией функции кросс-таблицы pandas в сценарии SQL. У меня есть таблица, которая выглядит так:

User   | Code   |  Used  
user1  | <null> |   1    
user2  | abca   |   4
user2  | <null> |   2
---
userN  | baaa   |   3   

Моя цель - таблица, подобная этой:

       | <null> |  abca  |  baaa  
user1  |   1    |   0    |   0    
user2  |   2    |   4    |   0
---
userN  |   0    |   0    |   1  

До сих пор я использовал этот код, взятый из здесь , но он возвращает пустую таблицу:

DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)

SELECT @ColumnName= User FROM temp2

SET @DynamicPivotQuery = 
    N'SELECT * from (
    SELECT User, Code, Used
    FROM temp2) as src
    PIVOT
    (
        sum(Used) as sum FOR Code IN (' + @ColumnName + ')
    ) as piv'
EXEC sp_executesql @DynamicPivotQuery
SELECT @DynamicPivotQuery

Буквально используются сотни кодов, поэтому, очевидно, мне нужно использовать динамическую сводную таблицу, поэтому мне не нужно перечислять все коды. Нулевые значения должны остаться. Я перепробовал практически все, что смог найти в Интернете и StackOverflow, включая , , , и многие другие. Буду признателен за любые выводы.

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

PIVOT не может обрабатывать значения NULL как группы. Вот почему кросс-табы предпочтительнее в этом случае. Вы также должны изменить свое состояние, чтобы выполнить сравнение и избежать дальнейших проблем.

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = N'SELECT [User] ' + NCHAR(10) 
         + ( SELECT ',SUM( CASE WHEN Code ' + ISNULL( '= ' + QUOTENAME( Code, ''''), 'IS NULL') + ' THEN Used ELSE 0 END) AS ' + QUOTENAME(ISNULL( Code, 'NULL')) + CHAR(10)
            FROM temp2 
            GROUP BY Code
            FOR XML PATH(''), TYPE).value('./text()[1]', 'nvarchar(max)')
         + N'FROM temp2' + NCHAR(10) 
         + N'GROUP BY [User];'
PRINT @SQL;
EXEC sp_executesql @SQL;  
1 голос
/ 29 апреля 2019

Если ваше значение равно NULL, а не '<null>', то, похоже, вы получите то, что вам нужно:

CREATE TABLE dbo.SampleTable ([User] varchar(6), --I suggest a different name here, USER is a reserved keyword in T-SQL
                               Code varchar(4),
                               Used tinyint);
INSERT INTO dbo.SampleTable ([User],
                              Code,
                              Used)
VALUES ('user1','null',1),    
       ('user2','abca',4),
       ('user2','null',2),
       ('userN','baaa',3);
GO

DECLARE @SQL nvarchar(MAX);
DECLARE @NL nchar(2) = NCHAR(13) + NCHAR(10)

SET @SQL = N'SELECT [User],' + @NL + 
           STUFF((SELECT N',' + @NL +
                         N'       MAX(CASE WHEN Code = ' + QUOTENAME(Code,'''') + N' THEN Used END) AS ' + QUOTENAME(COALESCE(Code,'null'))
                  FROM dbo.SampleTable ST
                  GROUP BY ST.Code
                  ORDER BY ST.Code
                  FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,10,N'') + @NL + 
           N'FROM dbo.SampleTable' + @NL + 
           N'GROUP BY [User];';
PRINT @SQL;

EXEC sp_executesql @SQL;

GO

DROP TABLE dbo.SampleTable;

Я изменил метод здесь, так как я предпочитаю создавать кросс-таблицу для сводных данных и не использовал переменную для получения значений столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...