SQL从3个表创建视图

Posted

技术标签:

【中文标题】SQL从3个表创建视图【英文标题】:SQL Creating view from 3 tables 【发布时间】:2018-07-18 13:39:27 【问题描述】:

我有三个表:Products、Attributes 和 AttributesDefinitions。

产品: +----+------+ | Id | Name | +----+------+ | 1 | Shoe1| +----+------+ | 2 | Shoe2| +----+------+ | 3 | Shoe3| +----+------+

属性定义: +----+---------+ | Id | Name | +----+---------+ | 1 | Color | | 2 | Type | | 3 | Destiny | +----+---------+

属性:

+----+--------------+--------------+-----------+ | Id | Value | DefinitionId | ProductId | +----+--------------+--------------+-----------+ | 1 | Brown | 1 | 2 | | 2 | Yellow | 1 | 1 | | 3 | Sport | 3 | 1 | | 4 | Jelly shoes | 2 | 1 | | 5 | Normal shoes | 2 | 2 | +----+--------------+--------------+-----------+

在 AttributesDefinitions 我想要属性定义。

在属性中我有属性和它们的值。

每个产品都有许多属性,但每种类型只有一个(属性定义)。

我的任务是创建一个包含产品列表及其所有属性值的视图。 它应该是这样的:

ProductsWithAttributesView:

+---------+--------+--------------+---------+ | Product | Color | Type | Destiny | +---------+--------+--------------+---------+ | Shoe1 | Yellow | Jelly shoes | Sport | | Shoe2 | Brown | Normal shoes | NULL | | Shoe3 | NULL | NULL | NULL | +---------+--------+--------------+---------+ 这样做的目的是获取 B2B 平台上的产品列表,并能够按属性值对其进行过滤。

任何帮助我怎样才能做到这一点?

【问题讨论】:

到目前为止你尝试了什么? 你使用的是什么 rdbms? 问题是 SQL,所以我先看看 SQL 连接。 ***.com/questions/22489505/… 看看这个 我在 MS SQL 上工作。 【参考方案1】:

我使用 CaitLAN Jenner 的代码来展示我的解决方案,但我不确定您是否可以制作在添加新类别时动态适应的视图。

CREATE TABLE Products
(
Id INT PRIMARY KEY,
Name VARCHAR(255)
);

INSERT INTO Products (Id,Name)
VALUES (1,'Car'),(2,'Motorcycle'),(3,'Bicycle')

CREATE TABLE AttributesDefinition
(
Id INT PRIMARY KEY,
Name VARCHAR(255)
);

INSERT INTO AttributesDefinition (Id,Name)
VALUES (1,'Number of wheels'),(2,'People'),(3,'Engine')

CREATE TABLE Attributes
(
Id INT,
Name VARCHAR(255),
Value VARCHAR(255),
DefinitionId INT FOREIGN KEY REFERENCES AttributesDefinition (Id),
ProductId INT FOREIGN KEY REFERENCES Products (Id)
);

INSERT INTO Attributes (Id, Name, Value, DefinitionId, ProductId)
VALUES (1,'Number of wheels','4',1,1),
 (2,'Number of wheels','2',1,2),
 (3,'Number of wheels','2',1,3),
 (4,'People','4',2,1),
 (5,'People','2',2,2),
 (6,'People','1',2,3),
 (7,'Engine','V6',3,1),
 (8,'Engine','V2',3,2)


CREATE VIEW ProductsWithAttributesView AS
SELECT      
    products.Name as 'Products',
    atr1.Value As 'Number of wheels',
    atr2.Value As 'People',
    atr3.Value As 'Engine'
FROM Products AS products
LEFT JOIN Attributes AS atr1 ON atr1.ProductId = products.Id AND atr1.DefinitionId = 1
LEFT JOIN Attributes AS atr2 ON atr2.ProductId = products.Id AND atr2.DefinitionId = 2
LEFT JOIN Attributes AS atr3 ON atr3.ProductId = products.Id AND atr3.DefinitionId = 3

结果

Products  | Number of wheels |  People | Engine
Car       |  4               |   4     | V6
Motorcycle|  2               |   2     | V2
Bicycle   |  2               |   1     | NULL

编辑。这个带枢轴的:

CREATE VIEW ProductsWithAttributesView2 AS
WITH pivot_data AS
(
SELECT products.Name as Products, -- Grouping Column
def.Name as AtrName, -- Spreading Column
Value -- Aggregate Column
FROM Attributes atr
INNER JOIN Products products ON atr.ProductId = products.Id 
INNER JOIN AttributesDefinition def ON def.Id = atr.DefinitionId 
)
SELECT Products, [Number of wheels],[People],[Engine]
FROM pivot_data
PIVOT (max(value) FOR AtrName IN ([Number of wheels],[People],[Engine])) AS p;

【讨论】:

我之前没有使用 PIVOTS 的经验,我正在挖掘这个主题的 ATM。我编辑了我的第一篇文章,提供了更多信息。【参考方案2】:

正如我在评论中所说,我非常不同意您所描述的架构,因为在我看来 Products 表应该与 Attributes 具有一对多或多对多的关系。也就是说,一个产品可以有多个属性,多个产品可以共享同一个属性。此外,由于您提到的设计以及您的最终目标是什么(具有任意长度的属性列表作为列的产品),您所要求的可能是不可能的。您可以通过在视图定义中精心设计的 PIVOT 语句来实现这些结果。首先让我知道下面的代码是否有效。

综上所述,如果我假设您使用的是 T-SQL,那么此代码将创建您描述的表并创建一个基于对表执行 JOIN 的视图。希望这能推动您朝着正确的方向前进。

CREATE TABLE Products
(
Id INT PRIMARY KEY,
Name VARCHAR(255)
);

CREATE TABLE AttributesDefinition
(
Id INT PRIMARY KEY,
Name VARCHAR(255)
);

CREATE TABLE Attributes
(
Id INT,
Name VARCHAR(255),
Value VARCHAR(255),
DefinitionId INT FOREIGN KEY REFERENCES AttributesDefinition (Id),
ProductId INT FOREIGN KEY REFERENCES Products (Id)
);


CREATE VIEW ProductsWithAttributesView AS
SELECT p.Name AS Products
,ad.Name AS AttributeDefinition
,a.Name AS AttributeName
,a.Value AS AttributeValue
FROM Products p 
INNER JOIN Attributes a ON p.Id = a.ProductId
INNER JOIN AttributesDefinition ad ON ad.Id = a.DefinitionId;

SELECT * FROM ProductsWithAttributesView;

【讨论】:

对于数据库设计,我绝对无能为力。 我添加了这个任务的目的。也许还有另一种更好的方法来解决这个问题。

以上是关于SQL从3个表创建视图的主要内容,如果未能解决你的问题,请参考以下文章

sql2005 中的把2个表创建成一个视图

在数据库中创建视图最多可以连接多少个表?连接表多了有啥影响…

SQL入门经典之视图

SQL入门经典 之视图

从视图中的 SQL 子查询返回值列表

SQL 从视图中的 4 个表中选择