У меня есть две таблицы, из которых я хочу сравнить данные. Запрос первой таблицы приведен ниже и дает мне 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, НО ВЫХОД НЕ ПРАВИЛЬНЫЙ
Минимальный воспроизводимый пример — отличное начало при обращении за помощью по SQL.
Удаление DISTINCT ничего не изменило. Вывод остается прежним.
Точно. В этом не было необходимости.
Поскольку в вашем вопросе нет примеров данных, я попытался решить эту проблему логически.
Создайте две разные таблицы представления: 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
)
Анализ был отличным, но вернулся с ошибкой. Я пытался разобраться в проблеме, но это не работает.
Ваша таблица t1
и t2
дает правильный результат? Можете ли вы проверить, в каком разделе UNION
возникла проблема? Можете ли вы поделиться примерами данных? @FolasopeOludairo
Проблема заключается в части запроса из UNION ALL. Пытаюсь разобраться в проблеме. Запрос выполняется очень хорошо, за исключением части объединения ALL.
Причина, по которой UNION ALL не работал, заключалась в том, что предыдущий запрос имел 5 столбцов, и вы хотите сопоставить его с двумя запросами UNION ALL, каждый из которых имел по 4 столбца в вашем выборе. Можете ли вы переписать запросы, начиная с части сценариев UNION ALL. Спасибо
Спасибо @Art Bindu. Ниже представлена модифицированная версия того, что вы написали на UNION ALL, и она отлично работает.
О, ок, ок, я понимаю, в чём я ошибся. @FolasopeOludairo Во время запроса UNION ALL
я пропустил прокси-столбцы раздела (A-B) и (BA) ... следующим образом: ' ' as TsrAmount,
& ' ' as CRAmount
. . . Пожалуйста, все эти колонки. Я обновил запрос
Что случилось с GROUP BY
?
Эмулируйте 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
.Я создал (маленькую) СКРИПКУ
Да, @RickJames, это тоже хорошая идея. Спасибо
SELECT DISTINCT
,GROUP BY
иUNION
удаляют дубликаты. Т.е. здесь абсолютно нет причин дляSELECT DISTINCT
, это просто вызывает у многих удивление.