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

#sql #postgresql #outer-join

#sql #postgresql #внешнее объединение

Вопрос:

Я изо всех сил пытаюсь объединить три таблицы с помощью внешнего соединения, но не могу сделать это правильно, я использую базу данных PostgreSQL .. Мои таблицы выглядят так:

мои таблицы

В моей таблице заказов есть внешний ключ клиентов и лет (эти два не имеют никакого отношения), некоторые год и клиент не представлены в моей таблице заказов. Я пытаюсь выполнить SQL-запрос, чтобы у каждого клиента был весь год. Я могу получить этот результат путем перекрестного объединения клиента и года, но этот подход не работает, когда я продолжаю объединять этот результат с другими таблицами. (В моей таблице заказов есть и другие внешние ключи, к которым я также должен присоединиться) Так могу ли я получить этот результат, используя вместо этого внешнее соединение?

Я пытался:

 Select* From Orders
RIGHT JOIN Customers on Orders.customer_id = customer.id
  

Это дает мне всех клиентов в таблице заказов (даже тех, у кого нет заказа), тогда я хотел бы сделать то же самое со всеми годами, чтобы у каждого клиента была одна строка для каждого года (2015-2020). Попытался выполнить другое правильное объединение с таблицей years, но это не сработало.. Кто-нибудь знает, как это исправить?

p.s имена таблиц не настоящие, я просто использовал эти имена, чтобы их было легче понять!

Ответ №1:

Если вы хотите, чтобы у всех клиентов был год и их соответствующие заказы, если они у них есть в год.

 SELECT CUS.ID AS CustomerID, CUS.Name AS CustomerName, YEA.year AS Year, ORD.ID AS OrderID 
FROM Customers AS CUS
   CROSS JOIN Years AS YEA
   LEFT JOIN Orders AS ORD 
        ON CUS.ID = ORD.Customer_ID
        AND ORD.YEAR_ID = YEA.ID;
  

Это предоставит вам и их порядкам отдельные строки.
Если вам нужно количество заказов, используйте это вместо:

 SELECT CUS.ID AS CustomerID, CUS.Name AS CustomerName, YEA.year AS Year, Count(ORD.ID) AS NrOfOrders 
FROM Customers AS CUS
   CROSS JOIN Years AS YEA
   LEFT JOIN Orders AS ORD 
        ON CUS.ID = ORD.Customer_ID
        AND ORD.YEAR_ID = YEA.ID
GROUP BY CUS.ID, CUS.Name, YEA.Year;
  

Который покажет количество заказов и предоставит каждому клиенту строку в год.

Попробуйте это / посмотрите это в действии здесь, я добавил некоторые данные, чтобы показать несколько заказов.

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

1. Спасибо Ди Крамер, это сработало отлично. Я не добавил этого: «И ORD.YEAR_ID = ДА. ИДЕНТИФИКАТОР», когда я сделал перекрестное соединение до этого, что является решением моей проблемы 🙂

Ответ №2:

CROSS JOIN Количество клиентов и лет, затем LEFT JOIN это с заказами, похоже, делает именно то, что вы описываете в своем сообщении. Или я что-то не так понимаю?

И в следующий раз не помещайте свои данные в изображение. Просто введите это / вставьте в свой пост, чтобы мы могли скопировать и вставить это в наши примеры… Мне пришлось перепечатать их…

А «имя» и «год» — это зарезервированные слова. Я избегал их в своем примере.

 pset null NULL
WITH 
-- your input ...
customers ( id, nm) AS (
          SELECT 1,'alpha'
UNION ALL SELECT 2,'bravo'
UNION ALL SELECT 3,'charlie'
UNION ALL SELECT 4,'delta'
UNION ALL SELECT 5,'echo'
UNION ALL SELECT 6,'foxtrot'
)
,
years(id,yr) AS (
          SELECT 1,2015
UNION ALL SELECT 2,2016
UNION ALL SELECT 3,2017
UNION ALL SELECT 4,2018
UNION ALL SELECT 5,2019
UNION ALL SELECT 6,2020
)
,
orders(id,cust_id,yr_id) AS (
          SELECT 1,1,1
UNION ALL SELECT 2,2,3
UNION ALL SELECT 3,4,5
UNION ALL SELECT 4,5,6
)
-- end of your input ...
SELECT
  cust.nm
, years.yr
, ord.id
FROM customers cust
CROSS JOIN years
LEFT JOIN orders ord ON ord.yr_id=years.id
ORDER BY 1,2
;
-- out    nm    |  yr  |  id  
-- out --------- ------ ------
-- out  alpha   | 2015 |    1
-- out  alpha   | 2016 | NULL
-- out  alpha   | 2017 |    2
-- out  alpha   | 2018 | NULL
-- out  alpha   | 2019 |    3
-- out  alpha   | 2020 |    4
-- out  bravo   | 2015 |    1
-- out  bravo   | 2016 | NULL
-- out  bravo   | 2017 |    2
-- out  bravo   | 2018 | NULL
-- out  bravo   | 2019 |    3
-- out  bravo   | 2020 |    4
-- out  charlie | 2015 |    1
-- out  charlie | 2016 | NULL
-- out  charlie | 2017 |    2
-- out  charlie | 2018 | NULL
-- out  charlie | 2019 |    3
-- out  charlie | 2020 |    4
-- out  delta   | 2015 |    1
-- out  delta   | 2016 | NULL
-- out  delta   | 2017 |    2
-- out  delta   | 2018 | NULL
-- out  delta   | 2019 |    3
-- out  delta   | 2020 |    4
-- out  echo    | 2015 |    1
-- out  echo    | 2016 | NULL
-- out  echo    | 2017 |    2
-- out  echo    | 2018 | NULL
-- out  echo    | 2019 |    3
-- out  echo    | 2020 |    4
-- out  foxtrot | 2015 |    1
-- out  foxtrot | 2016 | NULL
-- out  foxtrot | 2017 |    2
-- out  foxtrot | 2018 | NULL
-- out  foxtrot | 2019 |    3
-- out  foxtrot | 2020 |    4
  

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

1. Спасибо за ввод marcothesane, я забыл добавить строку в мое перекрестное соединение, когда я пробовал это раньше. Теперь это работает. Добавим данные, как вы указали в следующий раз, посмотрим, как это сделает больше смысла 🙂