2

我有一个具有唯一 id 的表 Items:itemId,... 行示例:'3506',...</p>

我有一个表 ItemProperties,其中包含以下列: itemId、datecreated、datemodified、property1、property2、property3、property4、property5

行示例:'3506'、'2012...'、'2012...'、'prop1'、'prop2'、'prop3'、'prop4'、'prop5'</p>

我需要将 ItemProperties 表的每一行拆分为 NewItemProperties 表中的 5 个单独的行,其中包含以下列: itemId、datecreated、datemodified、propertynumber、property

5行的示例:

‘3506’, ‘2012…’, ‘2012…’, 1, ‘prop1’

‘3506’, ‘2012…’, ‘2012…’, 2, ‘prop2’

‘3506’, ‘2012…’, ‘2012…’, 3, ‘prop3’

‘3506’, ‘2012…’, ‘2012…’, 4, ‘prop4’

‘3506’, ‘2012…’, ‘2012…’, 5, ‘prop5’

约束: - ItemProperties 的 itemId 不再出现在 Items 表中

  • 已经在 NewItems 表中的项目(id =id 和 propertynumber=property1~5 列的数量)不应被此过程覆盖/更新

  • 微软 SQL Server 2008 R2

  • ItemProperties 表中大约有 800000 行

我现在有非常慢的解决方案:

...

DECLARE c CURSOR read_only FOR SELECT * from ItemProperties

DECLARE @ID varchar(14), @CREA datetime, …

OPEN  c     

FETCH NEXT FROM c INTO @ID, @CREA, @MODI, @COL, @SIZE, @PAT, @YEAR, @ITEM

WHILE (@@fetch_status <> -1)

BEGIN

    IF (@@fetch_status <> -2)

    BEGIN
         select * from Items where itemId = @ID
         if @@ROWCOUNT = 0
               BEGIN
                    GOTO Fetch_Next
               END
         select * from ItemProperties where itemId = @ID AND propertynumber = 1
         if @@ROWCOUNT = 0
               INSERT INTO NewItemProperties
               VALUES(@ID, '1', @COL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
         select * from ItemProperties where itemId = @ID AND propertynumber = 2
         if @@ROWCOUNT = 0
               INSERT INTO NewItemProperties
               VALUES(@ID, '2', @SIZE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
     …

      END
    Fetch_Next:
    FETCH NEXT FROM c INTO @ID, @CREA, @MODI, @COL, @SIZE, @PAT, @YEAR, @ITEM
...

我可以通过删除创建和修改日期来优化我的 fetch 语句,但这就是我能想到的。我无法将其放入非透视查询中。基本上任何比光标更快的东西都会帮助我。欢迎所有想法。谢谢你。

4

3 回答 3

2

尝试这个

INSERT INTO NewItemProperties
SELECT itemId, '1', property1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
FROM ItemProperties 
UNION ALL
SELECT itemId, '2', property2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
FROM ItemProperties
......
UNION ALL
SELECT itemId, '5', property5, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
FROM ItemProperties
于 2012-12-17T19:56:36.240 回答
1

我不确定你为什么说你不能让它适应UNPIVOT. 但是您应该能够使用 anUNPIVOT来转换您的数据,然后将其插入到新表中。WHERE您可以在内部查询中添加任何子句条件。的关键UNPIVOT是数据具有相同的数据类型,因此如果需要,您可能必须将子查询中的数据转换为相同的数据类型:

insert into NewItemProperties(yourCcolsHere)
select itemid,
  datecreated, 
  datemodified,
  replace(col, 'property', '') col,
  value
from
(
 -- perform any datatype conversions here
  select i.itemid,
    p.datecreated,
    p.datemodified,
    p.property1, 
    p.property2, 
    p.property3, 
    p.property4, 
    p.property5
  from items i
  inner join ItemProperties p
    on i.itemid = p.itemid
) src
unpivot
(
  value
  for col in (property1, property2, property3,
              property4, property5)
) unpiv

请参阅带有演示的 SQL Fiddle

UNPIVOT函数执行与查询相同的功能UNION ALL

insert into NewItemProperties(yourCcolsHere)
select i.itemid,
    p.datecreated,
    p.datemodified,
    1 PropNumber,
    p.property1 value 
from items i
inner join ItemProperties p
  on i.itemid = p.itemid
union all
select i.itemid,
    p.datecreated,
    p.datemodified,
    2 PropNumber,
    p.property2 value
from items i
inner join ItemProperties p
  on i.itemid = p.itemid -- add more queries for the other properties

请参阅带有演示的 SQL Fiddle

于 2012-12-17T19:48:25.507 回答
0

我会通过定义一个返回所有要插入的内容的查询来做到这一点,然后插入它们:

with toinsert as (
     select ip.itemid, datecreated, datemodified, num as propertynumber
            (case when num = 1 then property1
                  when num = 2 then property2
                  when num = 3 then property3
                  when num = 4 then property4
                  when num = 5 then property5
             ) as property
     from ItemProperties ip cross join
          (select 1 as num union all select 2 union all select 3 union all select 4 union all select 5
          ) nums left outer join
          NewItemProperties nip
          on ip.itemid = nip.itemid and
             nums.num = nip.propertynumber
     where nip.itemid is null
    )
insert into NewItemProperties (itemid, datecreated, datemodified, propertynumber, property)
    select *
    from toinsert
于 2012-12-17T19:51:25.580 回答