T-SQL 查询将数据插入到具有可变列数的表中

Posted

技术标签:

【中文标题】T-SQL 查询将数据插入到具有可变列数的表中【英文标题】:T-SQL query to insert data into a table with a variable number of columns 【发布时间】:2020-07-23 12:32:17 【问题描述】:

我正在尝试将表 A 中的数据插入表 B 中,假设数据按其外观排序。

数据应该被加载到表B的方式是通过id_column。例如,id_column 为 1 的数据必须加载到 C01 列。请注意,并非所有数据都具有与 BLOCK 1 或 BLOCK 3 的 int 相同数量的 column_id。

我遇到的问题是表 B 并不总是具有相同数量的列。在这种情况下,它有 4 列,但它可能是 5 或更多或更少,所以我正在尝试的是让我有机会使用不同数量的列。

(当我之前创建表 B 时,我是考虑表 A 的最大 id_column 的)

请给点建议?

【问题讨论】:

SQL 表代表 无序 集合。您的结果取决于A 中的排序。你有指定排序的列吗? 【参考方案1】:

SQL 表代表无序 集合。您的排序假设表 A 中的排序,所以让我假设您有这样的列。

您可以分配一个分组,然后使用条件聚合:

select max(case when column_id = 1 then value end) as c01,
       max(case when column_id = 2 then value end) as c02,
       max(case when column_id = 3 then value end) as c03,
       max(case when column_id = 4 then value end) as c04,
       'X' as con
from (select a.*,
             sum(case when column_id = 1 then 1 else 0 end) over (order by <ordering col>) as grp
      from a
     ) a
group by grp;

这通过寻找column_id = 1 来分配组,这似乎表明一个新块的开始。

【讨论】:

感谢您的回答。我们必须记住,列数是动态的 @davide_pacman 。 . .您显然对 SQL 有误解。表没有动态的列数。这些列在create table 语句中是固定的(受alter table 约束)。【参考方案2】:

INSERT 语句无法处理动态列集。您必须指定要插入哪些列,这意味着您必须选择一组特定的列,并且与插入的顺序相同。

拥有像您所拥有的那样的表 A 是动态创建数据集的一种流行方法,拥有这样的表通常是数据库中该数据的结尾。大多数应用程序不会尝试以任何其他方式在数据库中解释该数据(例如也将其存储在表 B 中),而是从表 A 中进行选择,然后将数据解析到代码中的对象中。

对于具有未知列的数据集,我喜欢做的另一个选择是将未知部分存储在 xml 列中,然后为您知道的内容设置列。

一个例子是

CREATE TABLE tblData
(
   BlockID int NOT NULL PRIMARY KEY,
   Data xml
)

然后在代码中,您将使用所有随机列构建 xml 块。然后在代码中再次解析它。这为您提供了未知的灵活性。特别是如果其中一些未知列可能包含您不想为其他未知列保留的额外元数据。

【讨论】:

【参考方案3】:

不幸的是,您唯一的选择是使用动态 SQL 来做某事。下面是一些执行动态数据透视的示例代码。

CREATE TABLE #tblA
(
    BLK VARCHAR(100)
    ,COLUMN_ID INT
    ,VALUE VARCHAR(100)
)

INSERT INTO #tblA
(
    BLK
    ,COLUMN_ID
    ,VALUE
)
VALUES
('BLOCK 1', 1, 'AA')
,('BLOCK 1', 2, 'BB')
,('BLOCK 1', 3, 'CC')
,('BLOCK 2', 1, 'AAAA')
,('BLOCK 2', 2, 'BBBB')
,('BLOCK 2', 3, 'CCCC')
,('BLOCK 2', 4, 'DDDD')
,('BLOCK 3', 1, 'AAAAAA')
,('BLOCK 3', 2, 'BBBBBB')
,('BLOCK 3', 3, 'CCCCCC')
,('BLOCK 4', 1, 'AAAAAAAA')
,('BLOCK 4', 2, 'BBBBBBBB')
,('BLOCK 4', 3, 'CCCCCCCC')
,('BLOCK 4', 4, 'DDDDDDDD')

--END DEMO SETUP

DECLARE @sql NVARCHAR(MAX) = N'';
DECLARE @cols NVARCHAR(MAX) = N''

--BUILD LIST OF COLUMNS TO PIVOT
SELECT @cols += ',' + QUOTENAME('CO' + CAST(COLUMN_ID AS VARCHAR(10))) FROM #tblA GROUP BY COLUMN_ID
SELECT @cols = STUFF(@cols, 1,1,'')
--SELECT @cols

SELECT @sql = 'SELECT BLK, ' + @cols
    + ' FROM (' 
    + ' SELECT BLK, ''CO'' + CAST(COLUMN_ID AS VARCHAR(10)) AS ColName, Value FROM #tblA'
    + ') data'
    + ' PIVOT('
    + ' MAX(VALUE)'
    + ' FOR ColName IN  (' + @cols + ')'
    + ') AS pvt'
PRINT @sql
EXEC(@sql)

【讨论】:

以上是关于T-SQL 查询将数据插入到具有可变列数的表中的主要内容,如果未能解决你的问题,请参考以下文章

用于从连接表中进行选择的 T-SQL 查询,其中有可变数量的参数?

将记录插入到具有180列的表中

如何“扁平化”具有可变列数的 Spark 模式?

获取“where value in”的变量列

如何将具有未知列数的 ResultSet 映射到 List 并将其显示在 HTML 表中?

合并具有不同列数的表