выберите количество(*) результат в ЛЕВОМ ВНЕШНЕМ СОЕДИНЕНИИ такой же после переключения таблиц , я не могу понять, почему

#sql #postgresql #postgresql-12

Вопрос:

По мере того как я изучаю внешнее соединение слева, я пришел к выводу

Левое внешнее соединение B = все в A и общее в B, отражающее соответствующее значение в таблице результатов, другие значения A, которые не имеют общих значений с таблицей B, имеют нулевое значение в стороне B.

Таким образом, если A имеет 15 значений, B имеет 29 значений(5 общих), то результатом следующего запроса будет 15. Или, если A имеет 15 значений, B имеет 10 значений(5 общих), результат все равно будет 15.

 select count(*) from A left outer join B  on A.name=B.name;  

моя проблема:

У меня есть база данных dvdrental. Таблица клиентов, Таблица платежей. У них 599 14596 строк соответственно.

Когда я запускаю запрос: (я ожидал 14 596 и получил 14 596)

 select count(*) from payment left outer join customer on payment.customer_id=customer.customer_id;  

но когда я поменялся столами, то есть;( Я ожидал 599, но получил 14 596)

 select count(*) from customer left outer join payment on payment.cusotmer_id=customer.customer_id;  

почему? Я не могу понять. Справка

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

1. Может быть, у ваших клиентов несколько платежей? Возможно, вам придется объединить их, если вам нужна только одна платежная информация для каждого клиента.

2. Когда каждая строка в каждой таблице совпадает с другой таблицей, обычное внешнее соединение между таблицами между ожидаемыми ключами всегда будет возвращать (по крайней мере, но может быть и больше) количество строк в таблице привязки, поскольку нет случаев несоответствия. Это так же, как результат внутреннего соединения.

3. Предоставьте полный тестовый случай с CREATE TABLE инструкциями и INSERT утверждениями, с минимальным количеством строк, необходимых для создания поведения, которое вы не понимаете.

4. Когда все ключи совпадают в ваших таблицах, вы говорите A x B. И A x B — это то же самое, что B x A…..

5. Это означает, что у вас нет платежей незарегистрированных клиентов.

Ответ №1:

Это похоже на внутреннее соединение, так как нет несоответствий:

Примечание: Не стесняйтесь изменять имя val столбца customer_id на следующее. Результат будет тот же самый.

 WITH cte1 (id, val) AS (SELECT 1, 100 UNION SELECT 2, 100)  , cte2 (id, val) AS (SELECT 10, 100) SELECT COUNT(*)  FROM cte1 LEFT JOIN cte2 ON cte1.val = cte2.val ;  

и

 WITH cte1 (id, val) AS (SELECT 1, 100 UNION SELECT 2, 100)  , cte2 (id, val) AS (SELECT 10, 100) SELECT COUNT(*)  FROM cte2 LEFT JOIN cte1 ON cte1.val = cte2.val ;  

произведет такое же количество (2).

Ответ №2:

Я думаю, что реальная проблема заключается в том, какой из них вы выберете в качестве таблицы привязки. потому что он помещает другой поверх него и выполняет сложение. Здесь нет одного платежа клиента, например, когда мы смотрим на первую таблицу платежей, когда мы ставим счетчик на первую таблицу платежей, это приведет к 5 клиентам, потому что результат основан на таблице платежей. В другой возможности, когда таблица клиентов основана, она приносит шесть результатов. Как можно понять, какой из них вы выберете, зависит от базовой таблицы.

 --customer (count 6) , payment (5) WITH  payment(customer_id,paid) AS (SELECT 1,100 UNION SELECT 2,200 UNION SELECT 3,300 UNION SELECT 4,400 UNION SELECT 5,500 ) ,customer(customer_id) AS (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6)  SELECT COUNT(*) FROM payment py LEFT OUTER JOIN customer ct ON py.customer_id=ct.customer_id;   WITH  payment(customer_id,paid) AS (SELECT 1,100 UNION SELECT 2,200 UNION SELECT 3,300 UNION SELECT 4,400 UNION SELECT 5,500 ) ,customer(customer_id) AS (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6)  SELECT COUNT(*) FROM customer ct LEFT OUTER JOIN payment py ON py.customer_id=ct.customer_id;