左結合は、左のテーブルから行を返し、左のテーブルの各行について、右のテーブルの一致するすべての行を返します。
したがって、たとえば:
create table Customers (name varchar(50));
insert Customers values
('Tim'),
('John'),
('Spike');
create table Orders (customer_name varchar(50), product varchar(50));
insert Orders values (
('Tim', 'Guitar'),
('John', 'Drums'),
('John', 'Trumpet');
create table Addresses (customer_name varchar(50), address varchar(50));
insert Addresses values (
('Tim', 'Penny Lane 1'),
('John', 'Abbey Road 1'),
('John', 'Abbey Road 2');
次に、実行する場合:
select c.name
, count(o.product) as Products
, count(a.address) as Addresses
from Customers c
left join Orders o on o.customer_name = c.name
left join Addresses a on a.customer_name = c.name
group by name
あなたが得る:
name Products Addresses
Tim 1 1
John 4 4
Spike 0 0
しかし、ジョンは4つの製品を持っていません!
なしで実行するgroup by
と、カウントがオフになっている理由がわかります。
select *
from Customers c
left join Orders o on o.customer_name = c.name
left join Addresses a on a.customer_name = c.name
あなたが得る:
name customer_name product customer_name address
Tim Tim Guitar Tim Penny Lane 1
John John Drums John Abbey Road 1
John John Drums John Abbey Road 2
John John Trumpet John Abbey Road 1
John John Trumpet John Abbey Road 2
Spike NULL NULL NULL NULL
ご覧のとおり、結合は互いに繰り返されることになります。製品ごとに、アドレスのリストが繰り返されます。それはあなたに間違ったカウントを与えます。この問題を解決するには、他の優れた回答の1つを使用してください。
select c.name
, o.order_count
, a.address_count
from Customers c
left join
(
select customer_name
, count(*) as order_count
from Orders
group by
customer_name
) o
on o.customer_name = c.name
left join
(
select customer_name
, count(*) as address_count
from Addresses
group by
customer_name
) a
on a.customer_name = c.name
サブクエリにより、顧客ごとに1つの行のみが結合されます。結果ははるかに優れています:
name order_count address_count
Tim 1 1
John 2 2
Spike NULL NULL