1

我有的

我有一个 sql 数据库,其中有几个通过整数键相互关联的表。这是我的 3 个表、列名和每个表的一些示例数据。请记住,我只是输入这个来给出一个想法,它不是直接从数据库复制/粘贴(因此格式是为了传达这一点,而不是被 sql 数据库解析器读取。)

表格1

ItemTable
itemID,itemName, fruitOrVeggie, Color
1, Apple, Fruit, Red
2, Orange, Fruit, Orange
3, Carrot, Vegetable, Orange

表 2

AttributeTypesTable
attributeID,attributeName
1, Price
2, Weight
3, Diameter

表3

ItemAttributesTable
itemID,attributeID,attributeValue
1, 1, .75
1, 2, .5
1, 3, .7
2, 1, .9
2, 3, .7
3, 1, .3
3, 2, .5

请注意,我如何在 ItemAttributesTable 中为每个 itemID 提供多个条目——这是我试图在新表中合并的部分。

我想要的是

从这三个表中,我想创建一个这样的新表。

NewTable
itemID,itemName,fruitOrVeggie,Color,Price,Weight,Diameter
1, Apple, Fruit, Red, .75, .5, .7
2, Orange, Fruit, Orange, .9, , .7
3, Carrot, Vegetable, Orange, .3, .5, 

在这个 NewTable 中,itemID 是一个唯一键,因此每个 itemID 只有一个条目——这就是目标。请注意每个属性名称现在如何成为此新表中的一列,以及来自 ItemAttributesTable 的相应数据现在如何在此处列出,每个 itemID 都有一个条目(如果 ItemAttributesTable 没有该 itemID 的该属性 ID 的条目,则将字段留空) . 我不想在列名中硬编码,因为我的实际数据有大约十几个列,我希望这个查询足够通用,即使属性名发生变化也能够继续使用它,我添加或删除了一些他们等等

到那里怎么走

我主要看这种复杂查询所涉及的 sql,尽管实际上创建这个新表的某种 shell 可能会很好。例如,一个查询,然后是一个运行该查询以创建 ItemAttributesTable 的 Python 脚本。

关键部分是如何根据另一个表中的条目(在本例中为 attributeName)在新表中创建列,然后如何正确地从多个表中提取数据以填充这个新表。

4

2 回答 2

2

在 SQLServer2005+ 中,您可以使用PIVOT运算符来旋转表值表达式。SELECT...INTO创建一个新表并将查询的结果行插入其中

IF OBJECT_ID('NewTable') IS NOT NULL DROP TABLE NewTable
SELECT ItemID, ItemName, FruitOrVeggie, Color, Price, Weight, Diameter
INTO NewTable
FROM      
(      
 SELECT t.ItemID, t.ItemName, t.FruitOrVeggie, Color, attributeName, attributeValue
 FROM ItemTable t JOIN ItemAttributesTable at ON t.ItemID = at.ItemID
                  JOIN AttributeTypesTable tt ON at.attributeID = tt.attributeID
) x
PIVOT
(
 MAX(attributeValue) FOR attributeName IN ([Price], [Weight], [Diameter])
 ) p

SELECT *
FROM NewTable

SQLFiddle上的演示

或者

如果您有未知数量的列(属性名称)要转换,那么您可以使用动态 PIVOT。

DECLARE @cols AS nvarchar(max),
        @query AS nvarchar(max)

SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(attributeName)
                      FROM AttributeTypesTable
                      FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')

IF OBJECT_ID('NewTable') IS NOT NULL DROP TABLE NewTable                      
SET @query = 'SELECT ItemID, ItemName, FruitOrVeggie, Color, ' + @cols + 
             'INTO NewTable FROM 
             (
              SELECT t.ItemID, t.ItemName, t.FruitOrVeggie, Color, attributeName, attributeValue
              FROM ItemTable t JOIN ItemAttributesTable at ON t.ItemID = at.ItemID
                               JOIN AttributeTypesTable tt ON at.attributeID = tt.attributeID
              ) x
              PIVOT
              (
               MAX(attributeValue) FOR attributeName IN (' + @cols + ')
               ) p '

EXEC(@query)

SELECT *
FROM NewTable 

SQLFiddle上的演示

于 2013-02-09T09:50:31.030 回答
0

我会尝试这样的事情:

INSERT INTO NEW TABLE (itemID, itemName, fruitOrVeggie, Color, Price, Weight, Diameter)
SELECT IT.itemID, IT.itemName, IT.fruitOrVeggie, IT.Color, Price.attributeValue, Weight.attributeValue, Diameter.attributeValue
FROM ItemTable IT
LEFT OUTER JOIN ( SELECT itemId, attributeValue
        FROM ItemAttributesTable
        WHERE attributeID = 1
    ) AS Price
ON Price.itemID = IT.itemID
LEFT OUTER JOIN ( SELECT itemId, attributeValue
        FROM ItemAttributesTable
        WHERE attributeID = 2
    ) AS Weight
ON Weight.itemID = IT.itemID
LEFT OUTER JOIN ( SELECT itemId, attributeValue
        FROM ItemAttributesTable
        WHERE attributeID = 3
    ) AS Diameter
ON Diameter.itemID = IT.itemID

插入语法可能因您使用的特定 SQL 实现而异。我建议尝试 Select 部分,看看返回的行是否与您希望 newTable 中的行在运行插入之前的样子相匹配。

于 2013-02-09T03:45:32.907 回答