首页 >数据库 >mysql教程 >在 SQL 连接中使用多个'array_agg()”调用时如何避免行乘法?

在 SQL 连接中使用多个'array_agg()”调用时如何避免行乘法?

Patricia Arquette
Patricia Arquette原创
2024-12-31 14:26:14142浏览

How to Avoid Row Multiplication When Using Multiple `array_agg()` Calls in SQL Joins?

在单个查询中解析多个 array_agg() 调用

在处理涉及数组的多个联接时,必须了解它们对结果。在本例中,原始查询尝试提取每个员工的地址和工作日的数组。然而,由于多次联接而导致意外的行相乘,从而导致聚合不正确。

解决方案 1:先聚合,后加入

要解决此问题,有效的方法是在加入子查询之前聚合子查询中的数据。通过将聚合与联接分离,避免了行乘法的问题:

SELECT e.name, e.age, ad.streets, array_agg(wd.day) AS days
FROM (
   SELECT e.id, e.name, e.age, array_agg(ad.street) AS streets
   FROM employees e 
   JOIN address ad ON ad.employeeid = e.id
   GROUP BY e.id  -- PK covers whole row
) e
JOIN workingdays wd ON wd.employeeid = e.id
GROUP BY e.id, e.name, e.age;

解决方案 2:关联子查询或 JOIN LATERAL

用于对员工进行选择性过滤,可以使用相关子查询:

SELECT name, age
    , (SELECT array_agg(street) FROM address WHERE employeeid = e.id) AS streets
    , (SELECT array_agg(day) FROM workingdays WHERE employeeid = e.id) AS days
FROM employees e
WHERE e.namer = 'peter';  -- very selective

或者,LATERAL Postgres 9.3 或更高版本中可以使用联接:

SELECT e.name, e.age, a.streets, w.days
FROM employees e
LEFT JOIN LATERAL (
   SELECT array_agg(street) AS streets
   FROM address
   WHERE employeeid = e.id
   GROUP BY 1
) a ON true
LEFT JOIN LATERAL (
   SELECT array_agg(day) AS days
   FROM workingdays
   WHERE employeeid = e.id
   GROUP BY 1
) w ON true
WHERE e.name = 'peter';  -- very selective

这些替代方法可确保所有符合条件的员工都保留在结果中,避免之前的行乘法问题。

以上是在 SQL 连接中使用多个'array_agg()”调用时如何避免行乘法?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn