ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ НА ДВУХ ТАБЛИЦАХ MYSQL С 3 СВЯЗАННЫМИ КОЛОННАМИ

У меня есть две таблицы, из которых я хочу сравнить данные. Запрос первой таблицы приведен ниже и дает мне 12 строк. ***** 1-й запрос ************

SELECT distinct a.pnr AS PNR, a.station_code as Station,a.date as Date,
sum(a.allamount) as TsrAmount
from daily_posting a 
Where a.date between '2024-06-19' and '2024-06-19' and a.station_code in ('ABVS','BNIA','ABVH') 
group by a.date,a.station_code,a.pnr 

Второй аналогичный запрос дает мне 17 строк. ******* 2-й запрос *********

SELECT distinct b.pnr_NO AS PNR, b.sR_code as Station,b.date_OF_ACTION as Date,
ABS(
sum(b.LOC_TAX_AMOUNT + b.LOC_PAX_FARE + b.LOC_SURCHARGE_AMOUNT + b.LOC_SERVICE_FEE_AMOUNT )) 
as CRAmount 
from ticketsalesdetails b
Where b.date_of_action between '2024-06-19' and '2024-06-19' and b.sr_code in ('ABVS','BNIA','ABVH') 
group by b.date_of_action,b.sr_code,b.pnr_no

Мой вопрос: я хочу, чтобы полное внешнее соединение объединило эти две таблицы и разместило столбец «Сумма» рядом для целей сравнения. Mysql обрабатывает полное внешнее соединение, выполняя LEFT JOIN и используя UNION, чтобы объединить его с RIGHT join. Я использовал приведенный ниже запрос для выполнения полного внешнего соединения, но результаты неправильные. У меня должно получиться 17 строк. но в настоящее время он дает мне 12 строк, и значение суммы неверно

****** ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ *****

SELECT distinct a.pnr AS PNR, a.station_code as Station,a.date as Date,
sum(a.allamount) as TsrAmount, 
ABS(sum(b.LOC_TAX_AMOUNT + b.LOC_PAX_FARE + b.LOC_SURCHARGE_AMOUNT + b.LOC_SERVICE_FEE_AMOUNT )) as CRAmount 
from daily_posting a LEFT JOIN ticketsalesdetails b 
ON (a.pnr,a.DATE,a.station) = (b.PNR_no,b.date_of_action ,b.sr_code)
Where a.date between '2024-06-19' and '2024-06-19' and a.station_code in ('ABVS','BNIA','ABVH') 
group by a.date,a.station_code,a.pnr 

UNION

SELECT distinct a.pnr AS PNR, a.station_code as Station,a.DATE as Date,
sum(a.allamount) as TsrAmount, -1* sum(b.LOC_TAX_AMOUNT + b.LOC_PAX_FARE + b.LOC_SURCHARGE_AMOUNT + b.LOC_SERVICE_FEE_AMOUNT )  as CRAmount 
from daily_posting a RIGHT JOIN ticketsalesdetails b 
ON (a.pnr,a.DATE,a.station) = (b.PNR_no,b.date_of_action ,b.sr_code)
Where a.date between '2024-06-19' and '2024-06-19' and a.station_code in ('ABVS','BNIA','ABVH') 
group by a.date,a.station_code,a.pnr

Я выполнил ЛЕВОЕ СОЕДИНЕНИЕ И ПРАВОЕ СОЕДИНЕНИЕ И ОБЪЕДИНИЛ ОБА ЗАПРОСА С UNION, НО ВЫХОД НЕ ПРАВИЛЬНЫЙ

SELECT DISTINCT, GROUP BY и UNION удаляют дубликаты. Т.е. здесь абсолютно нет причин для SELECT DISTINCT, это просто вызывает у многих удивление.
jarlh 24.06.2024 11:17

Минимальный воспроизводимый пример — отличное начало при обращении за помощью по SQL.

jarlh 24.06.2024 11:17

Удаление DISTINCT ничего не изменило. Вывод остается прежним.

Folasope Oludairo 24.06.2024 11:39

Точно. В этом не было необходимости.

jarlh 24.06.2024 12:02
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
4
80
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Поскольку в вашем вопросе нет примеров данных, я попытался решить эту проблему логически.

Создайте две разные таблицы представления: A, B из daily_posting и TicketsalesDetails с одинаковым именем столбца.
Затем используйте UNION of INNER JOIN (A∩B) and Difference of two table (A-B, B-A) в соответствии с диаграммой ВЕННА ВНЕШНЕГО СОЕДИНЕНИЯ

Итак, ваш запрос должен быть:

WITH t1 AS (
    SELECT distinct a.pnr AS PNR, 
        a.station_code as Station,
        cast(a.date as DATE) as Date,
        sum(a.allamount) as amount
    from daily_posting a 
    Where   a.date between '2024-06-19' and '2024-06-19' 
        and a.station_code in ('ABVS','BNIA','ABVH') 
    group by a.date,a.station_code,a.pnr 
), t2 AS (
    SELECT distinct 
        b.pnr_NO AS PNR, 
        b.sR_code as Station,
        cast(b.date_OF_ACTION AS Date) as Date,
        ABS(sum(b.LOC_TAX_AMOUNT + b.LOC_PAX_FARE + b.LOC_SURCHARGE_AMOUNT + b.LOC_SERVICE_FEE_AMOUNT )) as amount 
    from ticketsalesdetails b
    Where b.date_of_action between '2024-06-19' and '2024-06-19' 
        and b.sr_code in ('ABVS','BNIA','ABVH') 
    group by b.date_of_action,b.sr_code,b.pnr_no
)

    SELECT t1.PNR,
        t1.Station,
        t1.DATE,
        t1.amount as TsrAmount, 
        t2.amount as CRAmount
    FROM t1 INNER JOIN t2
    ON      t1.PNR = t2.PNR 
        and t1.Station = t2.Station
        and t1.DATE = t2.DATE

UNION ALL 

    SELECT t1.PNR,
        t1.Station,
        t1.DATE,
        t1.amount as TsrAmount,
        '' as CRAmount
    FROM t1 
    WHERE NOT EXISTS (
        SELECT * FROM t2 
        where t1.PNR = t2.PNR 
            and t1.Station = t2.Station
            and t1.DATE = t2.DATE
    )

UNION ALL

    SELECT t2.PNR,
        t2.Station,
        t2.DATE,
        '' as TsrAmount,
        t2.amount as CRAmount
    FROM t2 
    WHERE NOT EXISTS (
        SELECT * FROM t1 
        where t2.PNR = t1.PNR 
            and t2.Station = t1.Station
            and t2.DATE = t1.DATE
    )    

Анализ был отличным, но вернулся с ошибкой. Я пытался разобраться в проблеме, но это не работает.

Folasope Oludairo 24.06.2024 16:02

Ваша таблица t1 и t2 дает правильный результат? Можете ли вы проверить, в каком разделе UNION возникла проблема? Можете ли вы поделиться примерами данных? @FolasopeOludairo

Art Bindu 25.06.2024 07:31

Проблема заключается в части запроса из UNION ALL. Пытаюсь разобраться в проблеме. Запрос выполняется очень хорошо, за исключением части объединения ALL.

Folasope Oludairo 25.06.2024 12:52

Причина, по которой UNION ALL не работал, заключалась в том, что предыдущий запрос имел 5 столбцов, и вы хотите сопоставить его с двумя запросами UNION ALL, каждый из которых имел по 4 столбца в вашем выборе. Можете ли вы переписать запросы, начиная с части сценариев UNION ALL. Спасибо

Folasope Oludairo 25.06.2024 13:40

Спасибо @Art Bindu. Ниже представлена ​​модифицированная версия того, что вы написали на UNION ALL, и она отлично работает.

Folasope Oludairo 25.06.2024 13:48

О, ок, ок, я понимаю, в чём я ошибся. @FolasopeOludairo Во время запроса UNION ALL я пропустил прокси-столбцы раздела (A-B) и (BA) ... следующим образом: ' ' as TsrAmount, & ' ' as CRAmount . . . Пожалуйста, все эти колонки. Я обновил запрос

Art Bindu 25.06.2024 14:08

Что случилось с GROUP BY?

Rick James 06.07.2024 16:56

Эмулируйте FULL OUTER JOIN следующим образом:

WITH 
cte1 AS ( {query 1} ),
cte2 AS ( {query 2} ),
cte0 AS ( SELECT PNR, Station, Date FROM cte1
          UNION
          SELECT PNR, Station, Date FROM cte2 )
SELECT PNR, Station, Date, cte1.TsrAmount, cte2.CRAmount
FROM cte0
NATURAL LEFT JOIN cte1
NATURAL LEFT JOIN cte2;

В запросе предполагается, что PNR, Station и Date не равны NULL.

Если эти столбцы могут содержать NULL, используйте

WITH 
cte1 AS ( {query 1} ),
cte2 AS ( {query 2} ),
cte0 AS ( SELECT PNR, Station, Date FROM cte1
          UNION
          SELECT PNR, Station, Date FROM cte2 )
SELECT cte0.PNR, cte0.Station, cte0.Date, cte1.TsrAmount, cte2.CRAmount 
FROM cte0
LEFT JOIN cte1 ON cte0.PNR <=> cte1.PNR 
              AND cte0.Station <=> cte1.Station 
              AND cte0.Date <=> cte1.Date
LEFT JOIN cte2 ON cte0.PNR <=> cte2.PNR 
              AND cte0.Station <=> cte2.Station 
              AND cte0.Date <=> cte2.Date;

Более простой (и быстрый) способ получить FULL OUTER JOIN — получить желтый и оранжевый цвета с помощью одного SELECT и получить зеленый цвет с помощью второго SELECT:

SELECT ...
    FROM a
    ...
UNION ALL
    SELECT ...
        FROM b
        LEFT JOIN a ON ...
        ...
        WHERE a.id IS NULL

Примечания:

  • UNION ALL быстрее, чем UNION или UNION DISTINCT
  • Неясно, нужен ли GROUP BY.

Я создал (маленькую) СКРИПКУ

Luuk 06.07.2024 17:33

Да, @RickJames, это тоже хорошая идея. Спасибо

Art Bindu 08.07.2024 08:00

Другие вопросы по теме