В общем, я не вижу конкретной причины для этого - однако вы спросили.
Важно понимать, что реляционная модель не должна следовать модели ОО.Это стандартный способ представления Customer-Order-LineItem
.В этом нет ничего плохого.
Если я хочу найти все позиции, принадлежащие клиенту, я должен присоединиться через таблицу Order
, аналогично точке OO-точечная нотация (Customer.Order.LineItem
).
select *
from Customer as c
join Order as o on o.CustomerId = c.CustomerId
join LineItem as i on i.OrderId = o.OrderId
where CustomerID = 7 ;
Предположим, что я немного модифицирую ключи, например:
CustomerOrderId
- это порядокпорядковый номер для каждого клиента (1,2,3 ...), а CustomerOrderItemId
- порядковый номер отдельной позиции для каждого из заказов клиента (1,2,3 ...).Каждую из них легко создать, как в
-- next CustomerOrderId
select coalesce(max(CustomerOrderId), 0) + 1
from Order
where CustomerId = specific_customer_id;
-- next CustomerOrderItemId
select coalesce(max(CustomerOrderItemId), 0) + 1
from LineItem
where CustomerId = specific_customer_id
and CustomerOrderId = specific_customer_order_id;
Теперь, если я хочу найти позиции, принадлежащие клиенту (и некоторые данные о клиентах), я могу пропустить таблицу Order
.
select *
from Customer as c
join LineItem as i on i.CustomerId = c.CustomerId
where CustomerID = 7 ;
И если мне не нужны какие-либо конкретные данные из таблицы Customer
, присоединяться вообще не нужно.Сравните это с первым примером - помните, что целью было получить позиции.
select *
from LineItem
where CustomerID = 7 ;
Итак, с реляционной моделью, распространяя (естественные) ключи, вы не должны всегда "останавливаться накаждая станция на пути связи "в соединениях.
Что лучше?Зависит от того, кого вы спрашиваете.
Надеюсь, вы сможете воплотить основной принцип в своем примере - мне трудно работать с универсальным (A, B, C).