我有一个表具有唯一ID的项:itemId,... 行的示例:'3506',...
我有一个包含以下列的表ItemProperties: itemId,datecreated,datemodified,property1,property2,property3,property4,property5
一行示例:'3506','2012 ...','2012 ...','prop1','prop2','prop3','prop4','prop5'
我需要将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’
约束: - 不应处理具有不再位于Items表中的itemId的ItemProperties
此过程不应覆盖/更新NewItems表中的项(id = id和propertynumber = property1~5列的数量)
Microsoft 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语句,但这是我能想到的全部内容。我无法将其放入一个无法解析的查询中。基本上任何比光标更快的东西都会帮助我。欢迎所有想法。谢谢。
答案 0 :(得分: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
答案 1 :(得分:1)
我不确定为什么你说你无法让它适合UNPIVOT
。但您应该能够使用UNPIVOT
转换数据,然后将其插入新表中。您可以在内部查询中添加任何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
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
答案 2 :(得分: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