I am trying to create an output with a similar behaviour to FULL OUTER JOIN, with UNION in mysql
The queires I am trying to combine are the same with different time frame parameteres
EXAMPLE:
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
ERROR:
Table 'server.t2' doesn't exist
Single subqueries:
| Portal | Amount | |--------|-----------| | 3 | 250 | | 4 | 300 | | 8 | 400 | | 9 | 500 | | 10 | 600 |
| Portal | Amount | |--------|-----------| | 1 | 250 | | 3 | 200 | | 4 | 350 | | 8 | 450 | | 9 | 550 |
Desired Outcome:
| Portal | Amount | Amount2 | |--------|-----------|-----------| | 1 | NULL| 250 | | 3 | 250 | 200 | | 4 | 300 | 350 | | 8 | 400 | 450 | | 9 | 500 | 550 | | 10 | 600 | NULL|
Question: What is the right syntax? Would there be better alternatives in PHP backend to combine the outputs of these queries?
You must repeat the subqueries in each of the unioned queries:
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
If you are using MySql 8.0+, you can simplify the code with CTEs:
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
I just don't see the point for union all
here. Both queries are the same, only the date filter changes. So, use conditional aggregation:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.