Хорошо, поэтому я думаю, что я должен не понимать что-то о SQL-запросах. Это довольно многословный вопрос, поэтому спасибо, что нашли время, чтобы прочитать его (моя проблема в конце концов, все остальное - это просто контекст).
Я пишу систему бухгалтерского учета, которая работает с принципом двойного ввода - деньги всегда перемещаются между учетными записями, транзакция - 2 или более TransactionParts
строк, уменьшающих одну учетную запись и увеличивающих другую.
Некоторые строки TransactionParts
могут быть помечены как связанные с налогами, чтобы система могла составлять отчет об общем объеме продаж/покупок НДС и т.д., поэтому возможно, что одна транзакция может иметь два TransactionParts
, ссылающихся на одну и ту же учетную запись - один НДС, а другой нет. Чтобы упростить представление пользователю, у меня есть представление о объединении нескольких строк для одной и той же учетной записи и транзакции:
create view Accounting.CondensedEntryView as
select p.[Transaction], p.Account, sum(p.Amount) as Amount
from Accounting.TransactionParts p
group by p.[Transaction], p.Account
Затем я имею представление для расчета столбца текущего баланса следующим образом:
create view Accounting.TransactionBalanceView as
with cte as
(
select ROW_NUMBER() over (order by t.[Date]) AS RowNumber,
t.ID as [Transaction], p.Amount, p.Account
from Accounting.Transactions t
inner join Accounting.CondensedEntryView p on p.[Transaction]=t.ID
)
select b.RowNumber, b.[Transaction], a.Account,
coalesce(sum(a.Amount), 0) as Balance
from cte a, cte b
where a.RowNumber <= b.RowNumber AND a.Account=b.Account
group by b.RowNumber, b.[Transaction], a.Account
По причинам, которые я еще не разработал, определенная транзакция (ID = 30) не отображается в выписке по счету для пользователя. Я подтвердил это, запустив
select * from Accounting.TransactionBalanceView where [Transaction]=30
Это дало мне следующий результат:
RowNumber Transaction Account Balance
-------------------- ----------- ------- ---------------------
72 30 23 143.80
Как я уже говорил, для каждой транзакции должно быть не менее двух TransactionParts
, поэтому один из них не представляется на мой взгляд. Я предположил, что должна быть проблема с тем, как я написал свое представление, и запустить запрос, чтобы увидеть, нет ли чего-то еще:
select [Transaction], count(*)
from Accounting.TransactionBalanceView
group by [Transaction]
having count(*) < 2
Этот запрос не возвращает никаких результатов - даже для транзакции 30! Думаю, что я должен быть идиотом, я запускаю следующий запрос:
select [Transaction]
from Accounting.TransactionBalanceView
where [Transaction]=30
Он возвращает две строки! Таким образом, select *
возвращает только одну строку, а select [Transaction]
возвращает оба. После многократного поглаживания и повторного запуска последних двух запросов я пришел к выводу, что у меня нет ни малейшего представления о том, что происходит. Любые идеи?
Большое спасибо, если вы застряли со мной так далеко!
Edit:
Вот планы выполнения:
выберите *
выберите [Транзакция]
1000 строк каждый, следовательно, найти где-то еще место для хоста.
Изменить 2:
Для полноты, вот таблицы, которые я использовал:
create table Accounting.Accounts
(
ID smallint identity primary key,
[Name] varchar(50) not null
constraint UQ_AccountName unique,
[Type] tinyint not null
constraint FK_AccountType foreign key references Accounting.AccountTypes
);
create table Accounting.Transactions
(
ID int identity primary key,
[Date] date not null default getdate(),
[Description] varchar(50) not null,
Reference varchar(20) not null default '',
Memo varchar(1000) not null
);
create table Accounting.TransactionParts
(
ID int identity primary key,
[Transaction] int not null
constraint FK_TransactionPart foreign key references Accounting.Transactions,
Account smallint not null
constraint FK_TransactionAccount foreign key references Accounting.Accounts,
Amount money not null,
VatRelated bit not null default 0
);