从多个表中选择 - 一对多关系

Posted

技术标签:

【中文标题】从多个表中选择 - 一对多关系【英文标题】:Select from multiple tables - One to Many relation 【发布时间】:2017-01-24 05:11:06 【问题描述】:

我有这样的表:

餐桌产品

[ 标识 |姓名]

表格图片

[ 产品 ID |网址 |订单号]

餐桌价格

[ 产品 ID |组合 |货币 |价格]

表格数量

[ 产品 ID |组合 |数量]


表格产品与其他表格是一对多的关系。我需要查询表并得到类似这样的结果(伪数组):

[
    ProductId: 1,
    Name: 'Sample product',
    Images: [
        [url, 1],
        [url, 2]
    ],
    Prices: [
        [aaa, USD, 50.00],
        [aaa, EUR, 50.00],
        [bbb, USD, 59.00],
        [bbb, EUR, 59.00]
    ],
    Quantities: [
        [aaa, 5],
        [bbb, 3]
    ]
]

我现在的做法如下: 我查询所有产品,列出它们的 ID,然后使用 WHERE IN 子句查询每个表(图像、价格、数量)。当我拥有所有数据后,我开始解析 php 中的表格以获得所需的结构。

我想知道是否有更好的方法来提取这些数据,我有很多这样的不同表,并且为每个表创建配置解析器有点混乱和有问题。有没有可能mysql会承担我的一些负担?

谢谢

【问题讨论】:

您可以只使用一个带有左连接的查询来获得它,尽管它不会将结果显示为您的伪数组,它将是产品表的信息以及其他表的等效连接值.对你来说可以吗? 这就是人们使用 ORM 的原因,就像在最流行的 php 框架中发现的那样。看看 Doctrine2,Laravel 中的 Eloquent 或 Propel。本质上,您设置的映射类也可以让您指定连接。然后您可以在代码中使用对象,ORM 通常会为您加载关系,因此您不必在代码中一直关注编写 sql 语句,并且可以更自然地使用表示表的对象类及其相关数据。 @gview 我看不出 orms 是如何让这件事变得简单的。然后,我们努力帮助用户让 orms 正常工作 @Drew:你说得对,使用 ORM 附带的内置查询语言,有些查询要么效率低下,要么非常困难。在 Doctrine2 中,这就是为什么你不时下到 DBAL 并滚动一些 sql 的原因。 我不使用MySQL,但我知道在T-SQL 中有提示输出结果为XML。例如。 SELECT name FROM master.sys.tables FOR XML AUTO。也许MySQL 有类似的功能,但JSON?另外,我建议使用WHERE EXISTS SELECT(... 而不是WHERE Id IN(... 【参考方案1】:

此查询将为您解决问题:

SELECT product.id, product.name, 
(SELECT group_concat(CONCAT('["',images.url, '",',  images.order_number,']')) FROM images WHERE images.product_id = product.id GROUP BY (product.id)) AS IMAGES_LIST,
(SELECT GROUP_CONCAT(CONCAT('["',prices.combination, '","', prices.currency, '",', prices.price,"]" )) FROM prices WHERE prices.product_id = product.id GROUP BY (product.id)) AS PRICE_LIST,
(SELECT GROUP_CONCAT(CONCAT('["',quantites.combination, '",',  quantites.quantity,"]")) FROM quantites WHERE quantites.product_id = product.id GROUP BY (product.id)) AS Quantity_LIST
FROM product WHERE product.id = 1
先拿到产品 对于每个使用子查询的图像,我们可以获取相关图像,使用组 concat 我们可以在一个字段中获取它们 价格和数量也一样

【讨论】:

爱你! :) 我创建了简单的 Query-to-tree 查询构建器,它的工作原理就像一个魅力,为我节省了大量的工作。谢谢 如果我有多个级别的一对多关系,这将如何扩展? 1 A 有很多 B,每个 B 都有很多 C。【参考方案2】:

使用JOINs 比使用WHERE ... IN ... 更简单(如果设置了外键,效率更高)。

可以单独查询这些表以获取Product Id = 1 所需的数据,如下所示:

SELECT i.*
FROM Product prd
INNER JOIN Images i
ON prd.Id = i.Product_Id
WHERE Product_Id = 1;

SELECT prc.*
FROM Product prd
INNER JOIN Prices prc
ON prd.Id = prc.Product_Id
WHERE Product_Id = 1;

SELECT q.*
FROM Product prd
INNER JOIN Quantities q
ON prd.Id = q.Product_Id
WHERE Product_Id = 1;

【讨论】:

【参考方案3】:

我建议您使用包含 ProductID 的所有这些信息的单个结果集并在 PHP 中对其进行解析。它会让事情变得更简单。

SELECT prd.ProductId, prd.Name, i.Url, i.Ordernumber, prc.Combination, prc.Currency, prc.Price,q.Combination, q.Quantity FROM Product prd INNER JOIN Images i ON prd.Id = i.Product_Id INNER JOIN Prices prc ON prd.Id = prc.Product_Id INNER JOIN Quantities q ON prd.Id = q.Product_Id WHERE Product_Id = 1;

【讨论】:

以上是关于从多个表中选择 - 一对多关系的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 多个一对多关系

一对多关系失败

从 2 个表中获取记录数 - 一对多关系

在一对多关系表中,仅从表A中获得在表B中具有多个对应行的那些行

如何使用 Django 查询从一对多关系中获取数据

Razor Pages - 一对多关系