2012-07-17 26 views
0

我有一个Excel电子表格中导入数据的平面表....SQL Server转换平表的属性基于结构

tbl_ProductsImport 
---------------------------------------------------------------------------------- 
ProductId | Name | Description | Attribute1 | Attribute2 | Attribute3 | Attribute4 etc... 
---------------------------------------------------------------------------------- 
12345  P1  Some desc.. x       x   x 
12346  P2  Some desc..    x    
12347  P3  Some desc.. x   x   x   x 
12348  P4  Some desc.. x          x 

我想将其转换成下表结构...

tbl_Products 
------------------------------ 
ProductId (pk) | Name | Description 

tbl_Attributes 
---------------------------------------------- 
AttributeId (pk) | Name (derrived from column) 

tbl_ProductAttributes 
---------------------- 
ProductId (fk) | AttributeId (fk) 

所以我问,我该怎么去写一个声明来做到这一点?

编辑:这将成为执行前截断所有现有数据的计划数据导入作业的一部分。

+0

是否有_some_'默认'属性集?什么是属性?特别是因为它们看起来非常漂亮(除非你在'productAttributes'中留下了一些东西)?否则,您将前往一个EAV(实体 - 属性 - 值)表,该表通常被视为SQL反模式。除此之外,他们通常很难有效地进行查询。另外,不要用'tbl_'前缀表 - 除此之外,如果您更改实际的模式,但将其重新创建为“传统”应用程序的视图,则看起来很奇怪。 – 2012-07-17 15:47:01

+0

这些属性的值并不重要,因为当字段的值为“x”时,我只需要将它们分配给特定的产品。为什么EAV通常包含SQL反模式?我还可以怎样去做这件事,以便让属性从导入变为导入,而不必每次都强制键入和重新设计我的消费应用程序? – 2012-07-17 16:10:11

+2

_How_值是否在进口之间变化(从Excel中推定)?根据发生的情况,最好通过更改基础模式_anyways_来实现。或者,它可能表明还有其他问题(比如,有人意外地格式化了一列错误)。 EAV通常被认为是反模式,因为它们有时被实施为真正应该是单行的东西(也就是说,所有属性都是必需的)。大多数情况下,EAV必须进行调整才能被智能地查询,并且会失去(本地)类型安全性(因为所有内容均以字符串形式存储)。 – 2012-07-17 16:25:54

回答

1

嗯。这会工作吗?讨厌的动态SQL,但有时它必须完成。

INSERT tbl_Products 
SELECT ProductId, Name, Description 
FROM tbl_ProductsImport 

INSERT tbl_Attributes (Name) 
SELECT c.name 
FROM sys.sysobjects o 
JOIN sys.syscolumns c ON o.id = c.id 
WHERE o.name = 'tbl_ProductsImport' 
AND  c.name LIKE 'Attribute%' 

DECLARE @DynamicSQL VARCHAR(MAX) 
SET  @DynamicSQL = '' 

DECLARE @AttributeId INT 
DECLARE @AttributeName NVARCHAR(255) 

SELECT @AttributeId = MIN(AttributeId) 
FROM tbl_Attributes 

WHILE (@AttributeId <= (SELECT MAX(AttributeId) FROM tbl_Attributes)) 
BEGIN 
    SELECT @AttributeName = Name 
    FROM dbo.tbl_Attributes 
    WHERE AttributeId = @AttributeId 

    SELECT @DynamicSQL = 
    'INSERT tbl_ProductAttributes 
    SELECT ProductId, ' + CONVERT(VARCHAR, @AttributeId) + ' 
    FROM tbl_ProductsImport 
    WHERE ' + @AttributeName + ' = 1' 

    EXEC (@DynamicSQL) 

    SET @AttributeId = @AttributeId + 1 
END 

这假定的值在tbl_ProductsImport属性是比特。没有尝试过,所以可能是超级失败。

Jim