使用新布局将数据从一个表移动到另一个表

时间:2017-10-31 20:39:59

标签: sql-server tsql

请注意,我之前曾问过此问题,但意识到我遗漏了一些非常重要的信息,并认为最好删除原始问题并发布新问题。我向所有人道歉........

我有一个包含以下列的表:

ID
Name
2010/Jan
2010/Jan_pct
2010/Feb
2010/Feb_pct
.....
.....
2017/Nov
2017/Nov_pct

然后是一个类似于每个月/年组合的列到现在(希望这是有道理的)。但请注意:并非每个月/年组合都存在。可能存在缺口或缺少月/年。例如,我知道2017年1月,2017年/ 2月失踪,可能有任何号码丢失。我只是不想列出每一栏,但要大致了解布局。

除此之外,数据库中没有一行,但是名称/ ID可以有多行,ID不是标识,但可以是任何数字。

为了了解表格的外观,这里有一些示例数据(请注意,我只添加了两个年/周组合,但有几十个不一定每月/每年一个)< / p>

ID     Name    2010/Jan    2010/Jan_Pct  2010/Feb    2010/Feb_Pct
10     Gold    81          0.00123       79          0.01242
134    Silver  82          0             75          0.21291
678    Iron    987         1.53252       1056        2.9897

您可以想象,这不是最好的设计,因为您需要每月添加一个新的两个新列。所以我创建了一个包含以下定义的新表

ID - float, 
Name - varchar(255), 
Month - varchar(3), 
Year - int, 
Value - int, 
Value_Pct - float

我试图找出如何将现有数据从旧表移动到新表设计中。

任何帮助都将非常感谢.....

1 个答案:

答案 0 :(得分:0)

您可以使用unpivot运算符来获取所需内容,只需添加一个组合unpivot运算符返回的额外行的步骤。

示例数据设置:

鉴于目标表的value数据类型int列和value_pct数据类型的float,我遵循现有数据表的相同数据类型指南

create table dbo.data_table
    (
        ID float not null
        , [Name] varchar(255) not null
        , [2010/Jan] int null 
        , [2010/Jan_Pct] float null
        , [2010/Feb] int null
        , [2010/Feb_Pct] float null
    )

insert into dbo.data_table
values (10, 'Gold', 81, 0.00123, 79, 0.01242)
    , (134, 'Sliver', 82, 0, 75, 0.21291)
    , (678, 'Iron', 987, 1.53252, 1056, 2.9897)

<强>答案:

--combine what was the "value" row and the "value_pct" row
--into a single row via summation
select a.ID
, a.[Name]
, a.[Month]
, a.[Year]
, sum(a.value) as value
, sum(a.value_pct) as value_pct
from (
    --get the data out of the unpivot with one row for value
    --and one row for value_pct. 
    select post.ID
    , post.[Name]
    , substring(post.col_nm, 6, 3) as [Month]
    , cast(substring(post.col_nm, 1, 4) as int) as [Year]
    , iif(charindex('pct', post.col_nm, 0) = 0, post.value_prelim, null) as value
    , iif(charindex('pct', post.col_nm, 0) > 0, post.value_prelim, null) as value_pct
    from (
        --cast the columns that are currently INT as Float so that 
        --all data points can fit in one common data type (will separate back out later)
        select db.ID
        , db.[Name]
        , cast(db.[2010/Jan] as float) as [2010/Jan]
        , db.[2010/Jan_Pct]
        , cast(db.[2010/Feb] as float) as [2010/Feb]
        , db.[2010/Feb_Pct]
        from dbo.data_table as db
        ) as pre
    unpivot (value_prelim for col_nm in (
                                        [2010/Jan]
                                        , [2010/Jan_Pct]
                                        , [2010/Feb]
                                        , [2010/Feb_Pct]
                                        --List all the rest of the column names here
                                        )
            ) as post
    ) as a
group by a.ID
, a.[Name]
, a.[Month]
, a.[Year]

最终输出:

Final Output