В модели данных, поставленной в вопросе, есть несколько ошибок.
Определение OUTSTANDING_FEES и AMOUNT в качестве столбцов varchar2
является неправильным моделированием данных, поскольку оба они, несомненно, предназначены для числовых (денежных) значений.Хорошей практикой всегда является использование наиболее подходящего типа данных для атрибута, который мы моделируем.
Создание внешнего ключа между OUTSTANDING_FEES и AMOUNT неверно, поскольку они не являются уникальными идентификаторами.Сумма денег, причитающаяся одному клиенту, может быть такой же, как сумма денег, причитающаяся любым другим, даже всем клиентам (в начале семестра все студенты должны платить одинаковую сумму за обучение).Итак, иностранец, который "ссылается на поля CUSTOMER_ID в обеих таблицах" - это все, что нужно.
Модель данных не предоставляет какого-либо атрибута, который позволяет намчтобы различать уплаченные сборы и сборы, которые не выплачены.
Спрашивающий утверждает, что "Я могу предположить, что любой идентификатор Customer_ID в таблице B появится только один раз втаблица ", но в реальной жизни мы ожидаем, что клиенты будут иметь несколько учетных записей, неоплаченных и оплаченных.Почему бы не смоделировать это?В противном случае, если между Клиентом и Комиссией действительно есть соотношение 1: 1, то нет необходимости в двух таблицах.
Итак, вот улучшенная модель.Он использует надлежащий тип данных для денежных значений;он применяет внешний ключ между двумя таблицами, используя CUSTOMER_ID;следовательно, он поддерживает отношения «один ко многим» между Клиентом и Комиссией;наконец, он отслеживает уплаченные и неоплаченные сборы.
create table customers
( customer_id integer not null constraint cust_pk primary key
, name varchar2(30) not null
, phone varchar2(12) not null
)
/
create table customer_fees
( fee_id integer not null constraint fees_pk primary key
, fee_type varchar2(20) not null
, amount number not null
, invoice_date date not null
, paid_date date null
, customer_id integer not null constraint fees_cust_fk references customers
)
/
А, а как насчет OUTSTANDING_FEES?Ну, эта информация выводится из данных в двух таблицах.Есть много способов написания этого запроса, этот подход является просто выбором:
select cust.customer_id
, cust.name
, cust.phone
, fees.outstanding_fees
from customers cust
left outer join
( select fees.customer_id
, sum(case when fees.paid_date is null then fees.amount
else 0 end) as outstanding_fees
from customer_fees fees
group by fees.customer_id ) fees on fees.customer_id = cust.customer_id
/
Обычно лучше рассчитывать агрегированные значения по требованию, чем пересчитывать их в каждой транзакции.Это масштабируется лучше, конечно, с объемами данных OLTP;физика хранилища данных отличается, но я не думаю, что в этом случае мы имеем дело с этим.