Расширенные (?) SQL соединения?

Я немного не понимаю, как это объяснить, поэтому я попытаюсь привести пример некоторых таблиц (+ данные), а затем результат, который мне нужен (все столбцы моей таблицы НЕ НУЛЕВЫЕ):

Table: Customers

Id int primary key
Name varchar(250)

Table: Stats (Date, CustomerId is the primary key)

Date (date)
CustomerId (int) - foreign key to Customers table
Earning (money)

Table: Bonus

Id int primary key
CustomerId int - foreign key to Customers table
Date date
Amount money

Table: Payments

Id int primary key
DateFrom date,
DateTo date,
CustomerId bigint - foreign key to Customers table

Table: CampaignPayment

Id int primary key
PaymentId int - foreign key to payments table
Quantity int
UnitPrice money

Table: BonusPayment

Id int primary key
PaymentId int - foreign key to payments table
Amount money

Идея здесь в том, что каждый раз, когда клиент делает что-то, что должно принести ему деньги, это попадает в таблицу статистики. Клиенты также могут получать различные виды бонусов, которые входят в таблицу бонусов. Время от времени мне нужно создать счет-фактуру для клиентов (таблица «Платежи»), в которой будут перечислены материалы из таблицы статистики + таблица бонусов за указанный период времени, и это будет генерировать счет-фактуру (то есть таблица платежей определяет, кто счет-фактура за какой период, а также таблица оплаты кампании и бонуса определяет, что выплачивается и почему).

Теперь мне нужно объединить все эти таблицы, чтобы получить следующие результаты:

CustomerId | CustomerName | PaymentId | Amount | BonusAmount | DateFrom | DateTo

Сумма — это суммированная сумма ( SUM(Quantity * UnitPrice)) из таблицы CampaignPayment, а BonusAmount — это суммированная сумма ( SUM(Amount) ) из таблицы BonusPayment. DateFrom и DateTo взяты из таблицы Payments.

Хитрость заключается в том, что для каждого клиента в течение данного месяца, где не охвачен каждый день этого месяца, мне нужна строка со следующими данными:

CustomerId | CustomerName | NULL | (Stats.Earning - Amount Earned from possible payments within the month) | (Bonus.Amount - Amount Earned possible bonuses that is in payments within the month) | First day of month | Last day of month

Мне может понадобиться немного более сложная логика, чтобы рассчитать сумму и сумму бонуса в этих «пустых» строках, но на данный момент это то, с чего мне нужно начать.

Как бы я это сделал? Я знаю, как сделать «начальный» бит, но как мне добавить эти «пустые» строки? Я надеюсь, что объяснил проблему достаточно подробно, и что вы можете увидеть идею здесь - если нет, дайте мне знать, и я попытаюсь объяснить дальше.

База данных MS SQL Server 2008.

РЕДАКТИРОВАТЬ: Также в качестве альтернативы допустимым решением является «пустая» строка для каждого клиента в месяц.


person kastermester    schedule 24.05.2009    source источник


Ответы (1)


Я бы сделал вспомогательную таблицу с «каждым днем ​​​​этого месяца», чтобы облегчить определение, если «каждый день месяца не охвачен» (несколько двусмысленная спецификация, но вспомогательная таблица должна помочь, имеете ли вы в виду «ни один день не указан»). покрывается" или "несколько дней не покрывается", и считается ли день "покрытым", если он имеет либо бонус или статистику, либо если для этого необходимо иметь и то, и другое. считаться "охваченным" - из-за этих неясностей я даже не собираюсь пытаться делать набросок SQL, используя эту вспомогательную таблицу ;-). Затем я бы UNION "пустые строки" до "начального бита", который вы уже знаете, как это сделать - кажется идеальной задачей для UNION!-)

person Alex Martelli    schedule 24.05.2009
comment
Спасибо, я попробую с этим. Единственное, что меня беспокоит в отношении объединения, это то, что это может закончиться повторением одной и той же задачи. Чтобы охватить дату, она должна отображаться в диапазоне в таблице «Платежи» (то есть DateFrom -> DateTo, обе даты ВКЛЮЧЕНЫ). Я все же посмотрю на это, спасибо :). - person kastermester; 24.05.2009
comment
Я предлагаю UNION, потому что это совсем не та та же задача, которую вы выполняете в начальных битовых и пустых строках. Чтобы определить покрываемые даты, учитывая вкладку aux со всеми интересующими датами Auxtab, которые я рекомендую, ВЫБЕРИТЕ дату ИЗ Auxtab JOIN Payments ON (дата МЕЖДУ DateFrom И DateTo) WHERE CustomerId=whatever ; чтобы определить непокрытые даты, ВЫБЕРИТЕ дату ИЗ Auxtab, ГДЕ НЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ * ИЗ платежей, ГДЕ adate МЕЖДУ DateFrom И DateTo И CustomerId = что угодно); и их варианты для оптимизации и т. д. (извините, место в комментарии закончилось, задайте еще один вопрос, если необходимо!-). - person Alex Martelli; 24.05.2009