ПОЛНОЕ ОБЪЕДИНЕНИЕ MySQL?

#mysql

#mysql

Вопрос:

Ниже приведен мой запрос, и я хочу получить результат, как указано ниже. Как я могу это сделать в mysql?

 SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
FULL JOIN Orders
ON Persons.P_Id=Orders.P_Id
ORDER BY Persons.LastName
  

Набор результатов должен выглядеть следующим образом:

 LastName      FirstName     OrderNo
Hansen        Ola          22456
Hansen        Ola          24562
Pettersen     Kari         77895
Pettersen     Kari         44678
Svendson      Tove   
                           34764
  

Комментарии:

1. Вы можете проголосовать за то, чтобы эта функция была реализована в MySQL

Ответ №1:

MySQL не поддерживает ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ.

Итак, если вы хотите эмулировать полное объединение в MySQL, посмотрите здесь .

Обычно предлагаемое обходное решение выглядит следующим образом:

 SELECT  t_13.value AS val13, t_17.value AS val17
FROM    t_13
LEFT JOIN
        t_17
ON      t_13.value = t_17.value
UNION ALL
SELECT  t_13.value AS val13, t_17.value AS val17
FROM    t_13
RIGHT JOIN
        t_17
ON      t_13.value = t_17.value
WHERE   t_13.value IS NULL
ORDER BY
        COALESCE(val13, val17)
LIMIT 30
  

Комментарии:

1. Как упорядочить все реестры по одному столбцу?

Ответ №2:

Различные типы объединений, для иллюстрации

Есть несколько методов для полного ПОЛНОГО [ВНЕШНЕГО] СОЕДИНЕНИЯ mysql.

  1. ОБЪЕДИНЕНИЕ левого соединения и правого соединения. ОБЪЕДИНЕНИЕ удалит дубликаты, выполнив операцию ORDER BY. Поэтому, в зависимости от ваших данных, это может быть неэффективно.

      SELECT * FROM A 
       LEFT JOIN B ON A.key = B.key 
    
     UNION 
    
     SELECT * FROM A 
       RIGHT JOIN B ON A.key = B.key
      
  2. ОБЪЕДИНИТЕ ВСЕ левое соединение и правое, ИСКЛЮЧАЯ соединение (это нижний правый рисунок на диаграмме). ОБЪЕДИНЕНИЕ ВСЕХ не приведет к удалению дубликатов. Иногда это может быть поведение, которое вы хотите. Вы также хотите использовать ПРАВОЕ ИСКЛЮЧЕНИЕ, чтобы избежать дублирования общих записей из выборки A и выборки B — т.е. Левое соединение уже включило общие записи из выборки B, давайте не будем повторять это снова с правым соединением.

      SELECT * FROM A 
       LEFT JOIN B ON A.key = B.key 
    
     UNION ALL
    
     SELECT * FROM A 
       RIGHT JOIN B ON A.key = B.key
       WHERE A.key IS NULL
      

Ответ №3:

 SELECT  p.LastName, p.FirstName, o.OrderNo
FROM    persons AS p
LEFT JOIN
        orders AS o
ON      o.orderNo = p.p_id
UNION ALL
SELECT  NULL, NULL, orderNo
FROM    orders
WHERE   orderNo NOT IN
        (
        SELECT  p_id
        FROM    persons
        )
  

Комментарии:

1. Как упорядочить все реестры по одному столбцу?

2. @Luitame: это должен быть другой вопрос, а не комментарий.

Ответ №4:

Попробуйте это:

 (SELECT p.LastName, p.FirstName, o.OrderNo
 FROM   Persons p
   LEFT JOIN Orders o
   ON o.OrderNo = p.P_id
)
UNION
(SELECT p.LastName, p.FirstName, o.OrderNo
 FROM   Persons p
   RIGHT JOIN Orders o
   ON o.OrderNo = p.P_id
);

 ---------- ----------- --------- 
| LastName | FirstName | OrderNo |
 ---------- ----------- --------- 
| Singh    | Shashi    |       1 |
| Yadav    | Sunil     |    NULL |
| Singh    | Satya     |    NULL |
| Jain     | Ankit     |    NULL |
| NULL     | NULL      |      11 |
| NULL     | NULL      |      12 |
| NULL     | NULL      |      13 |
 ---------- ----------- --------- 
  

Комментарии:

1. Важно соблюдать то, что UNION используется, а не UNION ALL

2. Здесь используется ОБЪЕДИНЕНИЕ, которое удалит дубликаты и выполнит операцию сортировки. Если вам нужен более производительный запрос или вы хотите сохранить дубликаты, используйте UNION ALL .

Ответ №5:

Хм, объединение ЛЕВОГО и ПРАВОГО СОЕДИНЕНИЯ с ОБЪЕДИНЕНИЕМ может сделать это:

 SELECT  p.LastName, p.FirstName, o.OrderNo
FROM    persons AS p
LEFT JOIN
        orders AS o
ON      p.P_Id = Orders.P_Id
UNION ALL
SELECT  p.LastName, p.FirstName, o.OrderNo
FROM    persons AS p 
RIGHT JOIN
        orders AS o
ON      p.P_Id = Orders.P_Id
WHERE   p.P_Id IS NULL
  

Ответ №6:

Полное объединение в mysql: (левое объединение справа) или (правое объединение слева)

  SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
    FROM Persons
    left JOIN Orders
    ON Persons.P_Id=Orders.P_Id
    ORDER BY Persons.LastName

    Union

    SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
    FROM Persons
    Right JOIN Orders
    ON Persons.P_Id=Orders.P_Id
    ORDER BY Persons.LastName
  

Комментарии:

1. Здесь используется ОБЪЕДИНЕНИЕ, которое удалит дубликаты и выполнит операцию сортировки. Если вам нужен более производительный запрос или вы хотите сохранить дубликаты, используйте ОБЪЕДИНЕНИЕ ВСЕХ

Ответ №7:

Другой альтернативой является использование временной таблицы и ВСТАВКИ ДУБЛИРУЮЩЕГО КЛЮЧА, подобного этому.

Создание образца данных:

 CREATE TABLE A (
AKEY INT PRIMARY KEY,
AVALUE DOUBLE
);

INSERT INTO A VALUES(1, 0.1); 
INSERT INTO A VALUES(2, 0.2);

CREATE TABLE B (
BKEY INT PRIMARY KEY,
BVALUE DOUBLE
);

INSERT INTO B VALUES(2, 0.2);
INSERT INTO B VALUES(3, 0.3);
  

Таблица данных:

 AKEY|AVALUE|
---- ------ 
   1|   0.1|
   2|   0.2|
  

Данные таблицы B:

 BKEY|BVALUE|
---- ------ 
   2|   0.2|
   3|   0.3|
  

Создание временной таблицы:

 CREATE TEMPORARY TABLE ABFULLJOIN (
ABKEY INT PRIMARY KEY,
AVALUE DOUBLE,
BVALUE DOUBLE
);
  

ВСТАВИТЬ В оператор ДУБЛИРОВАНИЯ КЛЮЧА:

 INSERT INTO ABFULLJOIN(ABKEY, AVALUE)
SELECT * FROM A;

INSERT INTO ABFULLJOIN(ABKEY, BVALUE)
SELECT * FROM B ON DUPLICATE KEY UPDATE BVALUE = B.BVALUE ;
  

Запрос ПОЛНОГО СОЕДИНЕНИЯ:

 SELECT * FROM ABFULLJOIN;
  

Результат:

 ABKEY|AVALUE|BVALUE|
----- ------ ------ 
    1|   0.1|      |
    2|   0.2|   0.2|
    3|      |   0.3|
  

УДАЛИТЬ временную таблицу:

 DROP TABLE ABFULLJOIN;
  

Ответ №8:

Здесь все правильно, но писать один и тот же запрос дважды — не очень хороший способ программирования… итак, у меня есть другой способ выполнить полное объединение в mysql, который заключается в следующем

 SELECT
 user_id , user_name, user_department 
FROM 
 (SELECT 
     user_id  , user_name , NULL as user_department 
  FROM
   tb_users 
 UNION 
   SELECT 
     user_id ,NULL as user_name , user_department
   FROM 
      tb_departments
 ) as t group by user_id