#sql #database #oracle
#sql #База данных #Oracle
Вопрос:
Я пытаюсь объединить результаты двух таблиц без дублирования / увеличения значений при использовании join. (у компании и команды есть идентификаторы из таблицы друг друга)
Я пытаюсь получить количество команд, которые поддерживают страну. и количество компаний, которые поддерживают страну.
Таблицы похожи на это.
companies | country
---------- --------
one | USA
two | CAN
tree | USA
four | MEX
и результатом будет подсчет количества сторонников для каждой страны.
country | company_no_supp
-------- ----------------
USA | 2
CAN | 1
MEX | 1
Теперь у меня было бы то же самое для team.
team | country
-------- ----------
t1 | CAN
t2 | CAN
t3 | CAN
t4 | MEX
t5 | MEX
t6 | USA
t7 | USA
t8 | USA
и результат:
country | team_no_supp
-------- -----------
USA | 3
CAN | 3
MEX | 2
Что я хочу сделать, так это объединить оба результата в один и сохранить team_no_supp и country_no_supp .
Нравится:
country | team_no_supp | companies_no_supp
-------- -------------- -------------------
USA | 3 | 2
CAN | 3 | 1
MEX | 2 | 1
Я пробовал объединения (все их разновидности). Однако у меня еще нет такого опыта в sql.
Комментарии:
1. Опубликуйте свой код, который вы пробовали до сих пор, в результатах (почему они не то, что вы хотите)
2. Пожалуйста, покажите, что вы пробовали…
Ответ №1:
Не используйте JOIN
, пока вам не нужно обогащать свои данные новыми атрибутами, вы можете использовать UNION
: он легче и обладает большими возможностями для параллельной обработки без большого обмена данными:
select
country,
count(team) as team_no_supp,
count(company) as companies_no_supp
from (
select
country,
company,
null as team
from companies
union all
select
country,
null as company,
team as team
from teams
)
group by country
db<> скрипка здесь
Комментарии:
1. Спасибо, я не узнал, как создавать подзапросы в from. это было очень полезно.
Ответ №2:
Попробуйте выполнить запрос ниже
SELECT TabAuxA.country,
team_no_supp,
company_no_supp FROM (SELECT country, COUNT(*) as company_no_supp
FROM table1
GROUP BY country ) as TabAuxA
INNER JOIN (SELECT country, COUNT(*) as team_no_supp
FROM table2
GROUP BY country ) as TabAuxB ON TabAuxA.country = TabAuxB.country
OBS:
Не забудьте заменить имена таблиц (table1 и table2) на таблицы, которые вы используете
Ответ №3:
Используйте подзапросы в предложении from:
select c.country, c.company_no_supp, t.teams_no_supp from
(select country, count(*) company_no_supp from @companies group by country) c
join
(select country, count(*) teams_no_supp from @teams group by country) t on c.country = t.country
Ответ №4:
Проблема в том, что у вас могут быть разные страны в обеих таблицах. Я бы предложил FULL JOIN
:
select country, coalesce(cnt_a, 0) as cnt_a,
coalesce(team_no_supp, 0) as team_no_supp
from (select country, count(*) as cnt_a
from a
group by country
) a full join
b
using (country);
Ответ №5:
Вот еще одно решение, которое также охватывает случай, когда не все страны присутствуют в обеих таблицах:
WITH companies (company, country)
AS
(
SELECT 'one', 'USA' FROM DUAL UNION ALL
SELECT 'two', 'CAN' FROM DUAL UNION ALL
SELECT 'tree', 'USA' FROM DUAL UNION ALL
SELECT 'four', 'MEX' FROM DUAL
), teams (team, country) AS
(
SELECT 't1', 'CAN' FROM DUAL UNION ALL
SELECT 't2', 'CAN' FROM DUAL UNION ALL
SELECT 't3', 'CAN' FROM DUAL UNION ALL
SELECT 't4', 'MEX' FROM DUAL UNION ALL
SELECT 't5', 'MEX' FROM DUAL UNION ALL
SELECT 't6', 'USA' FROM DUAL UNION ALL
SELECT 't7', 'USA' FROM DUAL UNION ALL
SELECT 't8', 'USA' FROM DUAL
), companies_cnt(country, cnt) AS
(
SELECT country, count(company) FROM companies
GROUP BY country
), teams_cnt(country, cnt) AS
(
SELECT country, count(team) FROM teams
GROUP BY country
), combined_data (country, t, c) AS
(
SELECT country, cnt, 0 FROM teams_cnt
UNION ALL
SELECT country, 0, cnt FROM companies_cnt
)
SELECT COUNTRY, MAX(t) as team_no_supp, MAX(c) as companies_no_supp from combined_data GROUP BY country;
Ответ №6:
Возможно, вы захотите использовать слияние, когда существует вставка, когда не существует обновление что-то вроде этого: ОБЪЕДИНИТЬ В employees e С ПОМОЩЬЮ hr_records h ВКЛ (e.id = h.emp_id) ПРИ СОВПАДЕНИИ ЗАТЕМ ОБНОВИТЕ НАБОР e.address = h.address ЕСЛИ НЕ СОВПАДАЮТ, ЗАТЕМ ВСТАВЬТЕ (id, address) ЗНАЧЕНИЯ (h.emp_id, h.адрес);