我需要将数据从非规范化数据库导出到多列到新的规范化数据库。
一个例子是 Products 表,它有30个布尔列(ValidSize1,ValidSize2 ecc ...),每个记录都有一个外键,指向 Sizes 表,其中有是30列,大小代码(XS,S,M等...)。为了获取产品的有效大小,我必须扫描两个表,并且只有在产品上的ValidSizeX为真时才从大小表中获取值SizeCodeX。像这样:
Products Table
--------------
ProductCode <PK>
Description
SizesTableCode <FK>
ValidSize1
ValidSize2
[...]
ValidSize30
Sizes Table
-----------
SizesTableCode <PK>
SizeCode1
SizeCode2
[...]
SizeCode30
现在我正在使用“模板”查询,我重复了30次:
SELECT
Products.Code,
Sizes.SizesTableCode, -- I need this code because different codes can have same size codes
Sizes.Size_1
FROM Products
INNER JOIN Sizes
ON Sizes.SizesTableCode = Products.SizesTableCode
WHERE Sizes.Size_1 IS NOT NULL
AND Products.ValidSize_1 = 1
我只是将这个查询放在一个循环中,然后用循环索引替换“_1”:
SET @counter = 1;
SET @max = 30;
SET @sql = '';
WHILE (@counter <= @max)
BEGIN
SET @sql = @sql + ('[...]'); -- Here goes my query with dynamic indexes
IF @counter < @max
SET @sql = @sql + ' UNION ';
SET @counter = @counter + 1;
END
INSERT INTO DestDb.ProductsSizes EXEC(@sql); -- Insert statement
GO
有更好,更清洁或更快的方法吗?我使用 SQL Server ,我只能使用 SQL / TSQL 。
谢谢!
答案 0 :(得分:0)
您可以使用SYS.Syscolumns表准备动态查询以获取行
中的所有值DECLARE @SqlStmt Varchar(MAX)
SET @SqlStmt=''
SELECT @SqlStmt = @SqlStmt + 'SELECT '''+ name +''' column , UNION ALL '
FROM SYS.Syscolumns WITH (READUNCOMMITTED)
WHERE Object_Id('dbo.Products')=Id AND ([Name] like 'SizeCode%' OR [Name] like 'ProductCode%')
IF REVERSE(@SqlStmt) LIKE REVERSE('UNION ALL ') + '%'
SET @SqlStmt = LEFT(@SqlStmt, LEN(@SqlStmt) - LEN('UNION ALL '))
print ( @SqlStmt )
答案 1 :(得分:0)
好吧,似乎“干净”(并且速度更快!)解决方案是UNPIVOT功能 我在这里找到了一个很好的例子:
http://pratchev.blogspot.it/2009/02/unpivoting-multiple-columns.html