我有一个像这样的MSSQL Server表:
id (auto-increment)
amount
date
account_id
全天插入数据。我现在需要一个视图来获取每天每个帐户的期初和期末金额。 我的麻烦是创建一个快速查询来访问最小值和最大值。 使用in语句创建一个只能访问最小值的视图很好,但是获得最小值和最大值都很棘手。我尝试过使用with子句,但查询速度非常慢。
BTW我将视图映射到hibernate,因此存储过程和函数将不会以相同的方式工作(我知道)。
更新 我想从我收到的回复中我的问题并不清楚。我想获得每个帐户的期初和期末余额。最大值和最小值是指按日期和account_id分组时获取最大值和最小值(id)。 我希望在id等于最大ID(期末余额)时获得金额,以及当id等于每个帐户每天的最小ID(期初余额)时的金额。
答案 0 :(得分:1)
SELECT account_id, date, MIN(amount), MAX(amount)
FROM <table>
GROUP BY account_id, date
你的问题肯定有些缺失。
答案 1 :(得分:1)
这样做,没有足够的数据来评估性能:
create table #accounts
(
id integer identity,
account_id integer,
amount decimal(18,3),
tran_date datetime
)
go
insert into #accounts values (1,124.56,'06/01/2009 09:34:56');
insert into #accounts values (1,125.56,'06/01/2009 10:34:56');
insert into #accounts values (1,126.56,'06/01/2009 11:34:56');
insert into #accounts values (2,124.56,'06/01/2009 09:34:56');
insert into #accounts values (2,125.56,'06/01/2009 10:34:56');
insert into #accounts values (2,126.56,'06/01/2009 11:34:56');
insert into #accounts values (3,124.56,'06/01/2009 09:34:56');
insert into #accounts values (3,125.56,'06/01/2009 10:34:56');
insert into #accounts values (3,126.56,'06/01/2009 11:34:56');
insert into #accounts values (4,124.56,'06/01/2009 09:34:56');
insert into #accounts values (4,125.56,'06/01/2009 10:34:56');
insert into #accounts values (4,126.56,'06/01/2009 11:34:56');
insert into #accounts values (1,124.56,'06/02/2009 09:34:56');
insert into #accounts values (1,125.56,'06/02/2009 10:34:56');
insert into #accounts values (1,126.56,'06/02/2009 11:34:56');
insert into #accounts values (2,124.56,'06/02/2009 09:34:56');
insert into #accounts values (2,125.56,'06/02/2009 10:34:56');
insert into #accounts values (2,126.56,'06/02/2009 11:34:56');
insert into #accounts values (3,124.56,'06/02/2009 09:34:56');
insert into #accounts values (3,125.56,'06/02/2009 10:34:56');
insert into #accounts values (3,126.56,'06/02/2009 11:34:56');
insert into #accounts values (4,124.56,'06/02/2009 09:34:56');
insert into #accounts values (4,125.56,'06/02/2009 10:34:56');
insert into #accounts values (4,126.56,'06/02/2009 11:34:56');
go
select
ranges.tran_day transaction_day,
ranges.account_id account_id,
bod.amount bod_bal,
eod.amount eod_bal
from
-- Subquery to define min/max records per account per day
(
select
account_id,
cast(convert(varchar(10),tran_date,101) as datetime) tran_day,
max(id) max_id,
min(id) min_id
from
#accounts
group by
account_id,
cast(convert(varchar(10),tran_date,101) as datetime)
) ranges
-- Beginning of day balance
JOIN #accounts bod
on (bod.id = ranges.min_id)
-- End of day balance
JOIN #accounts eod
on (eod.id = ranges.max_id)
go
如果您需要更好的性能,请先将子查询存储到临时表中,然后为其添加索引以进行连接...这可能会加快它的速度。
答案 2 :(得分:0)
根据John Saunders的回答和Jeremy的评论:
SELECT account_id, date, MIN(amount), MAX(amount)
FROM <table>
GROUP BY account_id, DatePart( Year, date ),DatePart( Month, date ), DatePart( Day, date )
答案 3 :(得分:0)
基本上我需要以下查询,但with语句会导致它运行缓慢:
with x as (
select
MAX(ab.id) as maxId, MIN(ab.id) as minId
from Balance ab
group by ab.account_id, dbo.Get_PeriodDateFromDatetime(ab.StatementDate)
)
select
ab.Amount as openingBalance, ab2.Amount as closingBalance
from Balance ab, Balance ab2, x
where ab.id = x.maxId and ab2.id = x.minId
答案 4 :(得分:0)
我不知道这是否有所改善,但您发布的查询看起来缺少某些部分,例如“with”查询中的account_id和主要部分中的account_id上的连接:
with x as (
select
ab.account_id, MAX(ab.id) as closeId, MIN(ab.id) as openId
from Balance ab
group by ab.account_id, dbo.Get_PeriodDateFromDatetime(ab.StatementDate)
)
select
opbal.account_id, opbal.StatementDate,
opbal.Amount as openingBalance, clsbal.Amount as closingBalance
from Balance opbal, Balance clbal, x
where clsbal.id = x.closeId
and clsbal.ccount_id = x.account_id
and opbal.id = x.openId
and op.account_id = x.account_id
我有点担心对dbo.Get_PeriodDateFromDatetime(ab.StatementDate)的调用:如果你有一个关于account_id和StatementDate的索引(你确实有那个索引,不是吗?它看起来像是一个很好的候选人也是一个聚集索引,然后它可能不是太糟糕,除非表格很大。
顺便说一下,“慢”的速度有多慢?