带有联合子查询的 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
我正在尝试创建一个与 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