带有联合子查询的 FULL OUTER JOIN

FULL OUTER JOIN with union subqueries

我正在尝试创建一个与 FULL OUTER JOIN 具有相似行为的输出,在 mysql

中使用 UNION

我尝试合并的问题是相同的,但时间范围参数不同

示例:

Select * from (
SELECT GGPORTAL as portal, sum(oa.GGAMOUNT) as amount FROM orders as o 
        left orderarticles as oa on o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
        where o.GGDATE >= '2020-01-01' and o.GGDATE <= '2020-12-31' 
        group by GGPORTAL
        ) as t1
        LEFT JOIN t2 ON t1.GGPORTAL = t2.GGPORTAL
UNION 
Select * from (
SELECT GGPORTAL as portal, sum(oa.GGAMOUNT) as amount2 FROM orders as o 
        left join orderarticles as oa on o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
        where o.GGDATE >= '2019-01-01' and o.GGDATE <= '2019-12-31' 
        group by GGPORTAL
        ) as t2
        RIGHT JOIN t1 ON t1.GGPORTAL = t2.GGPORTAL
        WHERE t1.GGPORTAL IS NULL

错误:

Table 'server.t2' doesn't exist

单个子查询:

| Portal | Amount    |
|--------|-----------|
|    3   |       250 |
|    4   |       300 |
|    8   |       400 |
|    9   |       500 |
|   10   |       600 |
| Portal | Amount    |
|--------|-----------|
|    1   |       250 |
|    3   |       200 |
|    4   |       350 |
|    8   |       450 |
|    9   |       550 |

期望的结果:

| Portal | Amount    | Amount2   |
|--------|-----------|-----------|
|    1   |       NULL|       250 |
|    3   |       250 |       200 |
|    4   |       300 |       350 |
|    8   |       400 |       450 |
|    9   |       500 |       550 |
|   10   |       600 |       NULL|

问题: 什么是正确的语法? PHP 后端是否有更好的替代方案来组合这些查询的输出?

您必须在每个联合查询中重复子查询:

SELECT * 
FROM (
  SELECT GGPORTAL portal, SUM(oa.GGAMOUNT) amount 
  FROM orders o LEFT JOIN orderarticles as oa 
  ON o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
  WHERE o.GGDATE >= '2020-01-01' and o.GGDATE <= '2020-12-31' 
  GROUP BY GGPORTAL
) t1 LEFT JOIN (
  SELECT GGPORTAL portal, SUM(oa.GGAMOUNT) amount 
  FROM orders o LEFT JOIN orderarticles as oa 
  ON o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
  WHERE o.GGDATE >= '2019-01-01' and o.GGDATE <= '2019-12-31' 
  GROUP BY GGPORTAL
) t2 ON t1.GGPORTAL = t2.GGPORTAL
UNION ALL
SELECT * 
FROM (
  SELECT GGPORTAL portal, SUM(oa.GGAMOUNT) amount 
  FROM orders o LEFT JOIN orderarticles as oa 
  ON o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
  WHERE o.GGDATE >= '2020-01-01' and o.GGDATE <= '2020-12-31' 
  GROUP BY GGPORTAL
) t1 RIGHT JOIN (
  SELECT GGPORTAL portal, SUM(oa.GGAMOUNT) amount 
  FROM orders o LEFT JOIN orderarticles as oa 
  ON o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
  WHERE o.GGDATE >= '2019-01-01' and o.GGDATE <= '2019-12-31' 
  GROUP BY GGPORTAL
) t2 ON t1.GGPORTAL = t2.GGPORTAL
WHERE t1.GGPORTAL IS NULL

如果您使用的是 MySql 8.0+,您可以使用 CTE 简化代码:

WITH 
  cte1 AS (
    SELECT GGPORTAL portal, SUM(oa.GGAMOUNT) amount 
    FROM orders o LEFT JOIN orderarticles as oa 
    ON o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
    WHERE o.GGDATE >= '2020-01-01' and o.GGDATE <= '2020-12-31' 
    GROUP BY GGPORTAL
  ),
  cte2 AS (
    SELECT GGPORTAL portal, SUM(oa.GGAMOUNT) amount 
    FROM orders o LEFT JOIN orderarticles as oa 
    ON o.GGAUFTRAGSNR = oa.GGAUFTRAGSNR 
    WHERE o.GGDATE >= '2019-01-01' and o.GGDATE <= '2019-12-31' 
    GROUP BY GGPORTAL
  ) 
SELECT * 
FROM cte1 t1 LEFT JOIN cte2 t2 
ON t1.GGPORTAL = t2.GGPORTAL
UNION ALL
SELECT * 
FROM cte1 t1 RIGHT JOIN cte2 t2 
ON t1.GGPORTAL = t2.GGPORTAL
WHERE t1.GGPORTAL IS NULL

我只是不明白 union all 这里的意义。这两个查询是相同的,只是日期过滤器发生了变化。所以,使用条件聚合:

slect ggportal as portal, 
    sum(case when o.ggdate >= '2020-01-01' and o.ggdate < '2021-01-01' then oa.ggamount else 0 end) as amount_2020,
    sum(case when o.ggdate >= '2019-01-01' and o.ggdate < '2020-01-01' then oa.ggamount else 0 end) as amount_2020
from orders as o 
left orderarticles as oa on o.ggauftragsnr = oa.ggauftragsnr 
where o.ggdate >= '2019-01-01' and o.ggdate < '2021-01-01' 
group by ggportal