Как объединить две таблицы, не повторяя одинаковые строки для разных значений в таблице - PullRequest
0 голосов
/ 19 февраля 2019

Первая таблица:

+ ---+-----------+
| id | country   |
+ ---+-----------+
| 1  | India     |
| 2  | Australia |
| 3  | Canada    |
| 4  | France    |
| 5  | Russia    |
+ ---+-----------+

Вторая таблица:

+ ---+-------+------------+
| id | user  | country_id |
+ ---+-------+------------+
| 1  | Ojas  | 1          |
| 2  | Raj   | 1          |
| 3  | John  | 3          |
| 4  | Robin | 2          |
| 5  | Mary  | 5          |
| 6  | Kamal | 4          |
| 7  | Bipin | 5          |
| 8  | Rohit | 1          |
+ ---+-------+------------+

Ожидаемый результат:

+ -----------+---------------+-------+
| country_id | country       | user  |
+ -----------+---------------+-------+
| 1          | India         | Ojas  |
| null       | null          | Raj   |
| null       | null          | Rohit |
| 2          | Australia     | Robin |
| 3          | Canada        | John  |
| 4          | France        | Kamal |
| 5          | Russia        | Mary  |
| null       | null          | Bipin |
+ -----------+---------------+-------+

Ответы [ 3 ]

0 голосов
/ 19 февраля 2019

Здесь вы можете использовать методы агрегирования методов mysql и PostgreSql GROUP_CONCAT и string_agg (some_column, ',') соответственно, чтобы объединить имена через запятую и получить по 1 записи для каждой страны.

Для Mysql

SELECT countries.id AS Id, countries.name AS Country, GROUP_CONCAT(DISTINCT users.name) as Users
FROM countries
INNER JOIN users ON users.country_id = countries.id
GROUP BY countries.id;

Для PostgreSql

SELECT countries.id AS Id, countries.name AS Country, string_agg(users.name, ',') as Users
FROM countries
INNER JOIN users ON users.country_id = countries.id
GROUP BY countries.id;

Результат будет выглядеть как

Id | Country     | User
---------------------------------
1  | India       | Ojas,Raj,Rohit
2  | Australia   | Robin
3  | Canada      | John
4  | France      | Kamal
5  | Russia      | Mary,Bipin
---------------------------------
0 голосов
/ 19 февраля 2019

Используйте LAG, чтобы увидеть, содержит ли предыдущая строка ту же страну.

select
  case when lag(c.id) over (order by c.id, u.user) = c.id then null else c.id end
    as country_id,
  case when lag(c.id) over (order by c.id, u.user) = c.id then null else c.country end
    as country,
  u.user
from countries c
join users u on u.country_id = c.id
order by c.id, u.user;

LAG является стандартным SQL и, соответственно, доступен во многих СУБД (Oracle, PostgreSQL, SQL Server, MySQL по состоянию наверсия 8, ...).

0 голосов
/ 19 февраля 2019

Если вы используете SQL Server, вы можете попробовать следующее:

SELECT c.id AS country_id, 
       c.country, 
       t.[user] 
FROM   (SELECT s.country_id, 
               s.[user], 
               Row_number() 
                 OVER ( 
                   partition BY s.country_id 
                   ORDER BY s.id) rn 
        FROM   @second s) t 
       LEFT JOIN @country c 
              ON t.country_id = c.id 
                 AND t.rn = 1 

Демонстрация в сети

Вывод

+------------+-----------+-------+
| country_id | country   | user  |
+------------+-----------+-------+
| 1          | India     | Ojas  |
+------------+-----------+-------+
| NULL       | NULL      | Raj   |
+------------+-----------+-------+
| NULL       | NULL      | Rohit |
+------------+-----------+-------+
| 2          | Australia | Robin |
+------------+-----------+-------+
| 3          | Canada    | John  |
+------------+-----------+-------+
| 4          | France    | Kamal |
+------------+-----------+-------+
| 5          | Russia    | Mary  |
+------------+-----------+-------+
| NULL       | NULL      | Bipin |
+------------+-----------+-------+

Для других баз данных:

Тот же запрос может быть написан без ROW_NUMBER(), как показано ниже, так что он будет работать на других базах данных, таких как mysql.

SELECT c.id AS country_id, 
       c.country, 
       t.user 
FROM   (SELECT s.country_id, 
               s.user, 
               s.id,
               CASE 
                 WHEN (SELECT Min(id) 
                       FROM   second s2 
                       WHERE  s2.country_id = s.country_id) = s.id THEN 1 
                 ELSE 0 
               END rn 
        FROM   second s) t 
       LEFT JOIN country c 
              ON t.country_id = c.id 
                 AND t.rn = 1 
ORDER  BY t.country_id ,t.id

MySQL db-fiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...