我有2张桌子。
Table1大约有2k列,如下所示:
Id A B C D E F G H...........................................AA
1
2
Table2有2列,看起来像:
Id Category
1 A
1 C
1 AA
2 B
2 D
我想在table1中插入并旋转table2的数据
表1最终应该看起来像
Id A B C D E F G H...........................................AA
1 1 0 1 0 0 0 0 0...........................................0
2 0 1 1 0 0 0 0 0...........................................0
我不确定如何在sql中执行此操作。非常感谢您提供任何帮助。
答案 0 :(得分:0)
关于sqlivot命令的绝对愚蠢的事情是,您必须知道/列出每一列。由于某种原因,Microsoft Access具有一种非常优雅的方式来旋转所有内容。因此,我什至不用费心使用透视命令。 Intead只是做大量案例和分组依据
select
id,
sum(case when category = 'A' then 1 else 0 end) as 'A',
sum(case when category = 'B' then 1 else 0 end) as 'B',
sum(case when category = 'C' then 1 else 0 end) as 'C',
etc...
from table2
group by id
我同意其他一些评论。如果您的情况允许,请考虑使用具有出色的透视/不透视命令的Excel PowerQuery或使用具有透视/转置工具的基于gui的工具,如Alteryx。快得多!
答案 1 :(得分:0)
我们可以使用动态sql生成具有必要列的数据透视查询并执行。
注意:我在缺失列中使用NULL而不是'0'来保持在8023 byes的允许最大稀疏数据大小之下。
如果table1中的a,b,c ... AA列为:
要检查此脚本是否可以运行,请运行下一个查询以检查是否小于类型所允许的字段。
~~~~
SELECT MAX([fields])
FROM (SELECT [fields] = COUNT(DISTINCT [category]) FROM [table2] GROUP BY [id]) AS [t]
~~~~
编辑:
~~~~
DECLARE @target_schema_name SYSNAME = N'dbo'; -- Modify if necessary
DECLARE @target_table_name SYSNAME = N'table1'; -- Modify if necessary
DECLARE @target_table_identifier SYSNAME = N'id'; -- Modify if necessary
DECLARE @source_schema_name SYSNAME = N'dbo'; -- Modify if necessary
DECLARE @source_table_name SYSNAME = N'table2'; -- Modify if necessary
DECLARE @source_table_identifier SYSNAME = N'id'; -- Modify if necessary
DECLARE @source_table_pivoter SYSNAME = N'category'; -- Modify if necessary
DECLARE @source_table_subquery_columns NVARCHAR(MAX) =
+ '[src].' + QUOTENAME(@source_table_identifier)
+ ','
+ '[src].' + QUOTENAME(@source_table_pivoter)
+ ','
+ '[auxiliar] = 1';
DECLARE @columns TABLE([name] SYSNAME);
INSERT INTO @columns ([name])
SELECT [c].[name]
FROM [sys].[schemas] AS [s]
INNER JOIN [sys].[tables] AS [t]
ON ([s].[schema_id] = [t].[schema_id])
INNER JOIN [sys].[columns] AS [c]
ON ([t].[object_id] = [c].[object_id])
WHERE (1 = 1)
AND ([s].[name] = @target_schema_name)
AND ([t].[name] = @target_table_name)
AND ([c].[name] <> @target_table_identifier)
AND ([c].[is_column_set] <> 1);
DECLARE @target_table_pivot_columns NVARCHAR(MAX) = NULL;
DECLARE @target_table_insert_columns NVARCHAR(MAX) = NULL;
DECLARE @source_table_insert_columns NVARCHAR(MAX) = NULL;
SELECT
@target_table_pivot_columns = IIF(@target_table_pivot_columns IS NULL, '', @target_table_pivot_columns + ',') + QUOTENAME([c].[name])
,@source_table_insert_columns = IIF(@source_table_insert_columns IS NULL, '', @source_table_insert_columns + ',') + QUOTENAME([c].[name]) --+ ' = ISNULL(' + QUOTENAME([c].[name]) + ', 0)'
FROM @columns AS [c];
SET @target_table_insert_columns = QUOTENAME(@target_table_identifier) + ',' + @target_table_pivot_columns;
SET @source_table_insert_columns = QUOTENAME(@source_table_identifier) + ',' + @source_table_insert_columns;
DECLARE @command NVARCHAR(MAX);
DECLARE @batch_min INT;
DECLARE @batch_max INT;
CREATE TABLE #ids ([id] INT, [batch] INT);
SET @command = '
INSERT INTO #ids ([id], [batch])
SELECT DISTINCT ' + QUOTENAME(@source_table_identifier) + ', (ROW_NUMBER() OVER (ORDER BY (SELECT 1)) - 1) / 10000
FROM ' + QUOTENAME(@source_schema_name) + '.' + QUOTENAME(@source_table_name) + ';
';
EXECUTE (@command);
SET @batch_min = 0;
SET @batch_max = (SELECT MAX([batch]) FROM #ids);
WHILE @batch_min <= @batch_max
BEGIN
SET @command = '
INSERT INTO ' + QUOTENAME(@target_schema_name) + '.' + QUOTENAME(@target_table_name) + '(' + @target_table_insert_columns + ')
SELECT ' + @source_table_insert_columns + '
FROM
(
SELECT ' + @source_table_subquery_columns + '
FROM ' + QUOTENAME(@source_schema_name) + '.' + QUOTENAME(@source_table_name) + ' AS [src]
INNER JOIN #ids AS [ids]
ON ([src].' + QUOTENAME(@source_table_identifier) + ' = [ids].[id])
WHERE (1 = 1)
AND ([ids].[batch] = ' + CONVERT(VARCHAR(11), @batch_min) + ')
) AS [src]
PIVOT (MAX([auxiliar]) FOR [category] IN (' + @target_table_pivot_columns + ')) AS [pvt]
';
EXECUTE (@command);
SET @batch_min += 1;
END
~~~~