使用密钥组合数据库条目以生成每个密钥一个条目的表

时间:2013-02-09 00:02:37

标签: sql

我有什么

我有一个sql数据库,其中有几个表由整数键相互关联。这是我的3个表,列名和每个表的一些示例数据。请记住,我只是输入它来提出一个想法,它不是从数据库直接复制/粘贴(因此格式化意味着传达点,不能被sql数据库解析器读取。)< / p>

表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只有一个条目 - 这就是目标。请注意每个attributeName现在是这个新表中的列,以及如何在此列出ItemAttributesTable中的相应数据,每个itemID都有一个条目(如果ItemAttributesTable没有该itemID的attributeID条目,则将该字段留空) 。我不想在列名中使用硬代码,因为我的实际数据有大约十几列,我希望这个查询具有足够的通用性,即使attributeName发生变化也能继续使用它,我添加或删除一些他们等等。

如何到达

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

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

2 个答案:

答案 0 :(得分: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上的演示

OR

如果您有一个未知数量的列(attributeName)进行转换,那么您可以使用动态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上的演示

答案 1 :(得分: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实现而异。我建议尝试选择部分,看看返回的行是否与运行插入前的newTable中的行相匹配。