在查询中从子表中获取连接行的更好方法是什么?

时间:2019-02-22 17:56:29

标签: php mysql join normalization

对于我的大学项目,我正在制作一个模型电子商务网站进行学习。我搜索了类似的问题,但是我无法获得更深入的想法。

我当前的表格结构:

  1. 产品-sku(PK),名称,价格,其他列
  2. ProductMedia-路径(唯一),product_sku(来自产品表)。

path包含媒体的文件名。

检索产品数据时,我从表中选择以下列:产品和LEFT JOIN productMedia和GROUP_CONCAT并获取路径。

查询:

SELECT
p.*, // for simplicity mentioned as *
(GROUP_CONCAT(path SEPARATOR ',') FROM productMedia WHERE product_sku = p.sku) as product_images
FROM products p
WHERE SOME_CONDITION

要显示,我explode product_images并循环显示或用于其他目的。

现在我的问题是:

  1. 这是有效的方法吗?还是我不知道的更好的方法?
  2. 当需要从子表(此处为productMedia)中连接多个列时,我多次写入GROUP_CONCAT (column SEPARATOR) as concatenatedColumn,这不会影响性能吗?

2 个答案:

答案 0 :(得分:1)

我尽量不要使用GROUP_CONCAT()来获取子行,如您所描述的情况。

我会执行以下更简单的查询:

SELECT p.*, m.* // really write out the columns, don't use * 
FROM products p
LEFT OUTER JOIN productMedia m ON m.product_sku = p.sk
WHERE <conditions on p>

此查询更易于编写和优化。

它确实为每个p返回可变数量的行,因为productMedia中可能有0、1或许多匹配的行。 p.*的每个匹配行将复制m的值。在获取行时,不难在应用程序代码中对其进行处理。

答案 1 :(得分:0)

形式上(取决于private Toolbar mTopToolbar; mTopToolbar = (Toolbar) findViewById(R.id.my_toolbar); setSupportActionBar(mTopToolbar); ,此条件必须放置在WHERE,HAVING或同时放置-以便在不弄清楚条件的情况下无法在查询中插入这样的通用占位符):

SOME_CONDITION

如果启用了SELECT p.*, GROUP_CONCAT(pm.path SEPARATOR ',') paths FROM Products p LEFT JOIN ProductMedia pm ON p.sku = pm.product_sku GROUP BY p.sku; ,则会出现错误。此查询对于部分分组是安全的,因此建议您更改此查询的会话SQL模式(所有3个查询必须在同一连接中强烈执行!最好的方法是在一个多查询语句中执行它们): / p>

ONLY_FULL_GROUP_BY

如果SET @@sql_mode := REPLACE((@old_sql_mode := @@sql_mode), 'ONLY_FULL_GROUP_BY', ''); SELECT p.*, GROUP_CONCAT(pm.path SEPARATOR ',') paths FROM Products p LEFT JOIN ProductMedia pm ON p.sku = pm.product_sku GROUP BY p.sku; SET @@sql_mode := @old_sql_mode; 中没有匹配的记录,则该产品将为NULL。如果NULL对您不安全,请改用ProductMedia

这是有效的方法吗?还是我不知道的更好的方法?

是的,它足够有效。当然,您可以为每条记录选择一个路径(并获得很多COALESCE(GROUP_CONCAT(pm.path SEPARATOR ','), '') paths字段值重复项)-这将稍微减少PHP的工作量,但会增加数据转换器和内存使用量。另外,在我的方法中,您不需要通过p.*对其他输出记录集进行预排序。

当需要从子表(此处为productMedia)连接多个列时,我多次编写p.sku

您可以为每个字段使用两个单独的GROUP_CONCAT,或将所有内容连接为一个值,例如

GROUP_CONCAT(column SEPARATOR) as concatenatedColumn

您可以同时使用相同的分隔符(然后在一个数组上爆炸和迭代)和不同的分隔符(并按记录爆炸,然后按字段爆炸每个记录值)。

这不会影响性能吗?

但是您需要此数据吗?所以没有办法,你必须做...

还有“性能差异”-与什么相比?