简体   繁体   中英

FULL OUTER JOIN with union subqueries

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM