#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, я забыл добавить строку в мое перекрестное соединение, когда я пробовал это раньше. Теперь это работает. Добавим данные, как вы указали в следующий раз, посмотрим, как это сделает больше смысла 🙂