Sql 如何有效地将数据从垂直数据库布局传输到水平数据库布局

Sql 如何有效地将数据从垂直数据库布局传输到水平数据库布局,sql,db2,bulkinsert,transfer,Sql,Db2,Bulkinsert,Transfer,我想从垂直db布局传输数据,如下所示: --------------------- | ID | Type | Value | --------------------- | 1 | 10 | 111 | --------------------- | 1 | 14 | 222 | --------------------- | 2 | 10 | 333 | --------------------- | 2 | 25 | 444 | ----------

我想从垂直db布局传输数据,如下所示:

--------------------- | ID | Type | Value | --------------------- | 1 | 10 | 111 | --------------------- | 1 | 14 | 222 | --------------------- | 2 | 10 | 333 | --------------------- | 2 | 25 | 444 | --------------------- --------------------- |ID |类型|值| --------------------- | 1 | 10 | 111 | --------------------- | 1 | 14 | 222 | --------------------- | 2 | 10 | 333 | --------------------- | 2 | 25 | 444 | --------------------- 到水平面:

--------------------------------- | ID | Type10 | Type14 | Type25 | --------------------------------- | 1 | 111 | 222 | | --------------------------------- | 2 | 333 | | 444 | --------------------------------- --------------------------------- |ID |类型10 |类型14 |类型25| --------------------------------- | 1 | 111 | 222 | | --------------------------------- | 2 | 333 | | 444 | --------------------------------- 创建布局不是一个问题,但是数据库相当大,有数百万条条目,如果查询需要花费很多时间,就会被取消


如何有效地完成这项工作(以便查询不会被取消)。

将其分解为更小的块,而不是将整个事务打包在一个事务中。首先,创建表,然后从旧表向新表中插入组。例如,按ID的范围插入足够小的数据块,这样不会占用数据库的日志,也不会花费太长时间

with t as
(
select 1 as ID, 10 as type, 111 as Value from dual
union
select 1, 14, 222 from dual
union
select 2, 10, 333 from dual
union
select 2, 25, 444 from dual
)
select ID,
max(case when type = 10 then Value else null end) as Type10,
max(case when type = 14 then Value else null end) as Type14,
max(case when type = 25 then Value else null end) as Type25
from t
group by id
返回您想要的,我认为这是更好的方法。 请注意,max函数只是在这里执行group by子句,这里可以使用任何group函数(如sum、min…)

垂直表(也称为实体属性值反模式)总是会成为一个问题,有时在付诸实践后很快就会成为问题。如果您还没有这样做,请查看Joe Celko对此策略的看法,您将看到更多的证据,证明这种方法有多么麻烦。我就到此为止,因为你是知道来这个网站的聪明人,而不是在你的数据库中犯下EAV表的有罪但善意的一方

处理这类表的选项并不漂亮,正如您所说的,随着生产查询所需数据量的增加,它们会变得更糟/更慢

  • 构建一个声明的全局临时表(DGTT),该表不记录并保留提交的行,并使用它来暂存EAV表内容的水平版本。DGTT适合于这种数据清除,因为它们不会产生任何日志开销

  • 如前一建议所示,使用传统的CASE和MAX()分组。问题在于,每次在EAV表中引入新类型时,查询都会发生更改

  • 使用DB2的SQL-XML发布特性将垂直数据转换为XML。下面是一个使用您提供的表名和列名的示例:




  • SQL-XML方法的好处是,EAV表处理的任何新值都不需要重写数据透视的SQL。

    我相信这通常被称为数据透视
    WITH t(id, type, value) as (
    VALUES (1,10,111), (1,14,222), (2,10,333), (2,25,444)
    )
    
    SELECT
    XMLSERIALIZE( CONTENT
    XMLELEMENT(NAME "outer",
        XMLATTRIBUTES(id AS "id"),
            XMLAGG(XMLELEMENT(NAME attr ,
                XMLATTRIBUTES(type as "typeid"), value) ORDER BY type)
    ) AS VARCHAR(1024)
    ) 
    FROM t as t group by id;