Как объединить столбцы в SQL?

#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.адрес);