|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
支持多种存储引擎。解答|微软
成绩:
一百个账户各有100$,某个账户某天若有付出则增加一条新纪录,纪录其他额。一百天后,请输入天天一切账户的余额信息
这个成绩的难点在于每一个用户在某天大概有多条记录,也大概一条记录也没有(不包含第一天)
前往的纪录集是一个100天*100个用户的记录集
上面是我的思绪:
1.创立表并拔出测试数据:我们请求username从1-100
CREATETABLE[dbo].[TABLE2](
[username][varchar](50)NOTNULL,--用户名
[outdate][datetime]NOTNULL,--日期
[cash][float]NOTNULL--余额
)ON[PRIMARY
declare@iint
set@i=1
while@i<=100
begin
inserttable2values(convert(varchar(50),@i),2001-10-1,100)
inserttable2values(convert(varchar(50),@i),2001-11-1,50)
set@i=@i+1
end
inserttable2values(convert(varchar(50),@i),2001-10-1,90)
select*fromtable2orderbyoutdate,convert(int,username)
2.组合查询语句:
a.我们必需前往一个从第一天入手下手到100天的记录集:
如:2001-10-1(这个日期是恣意的)到2002-1-8
因为第一天是恣意一天,以是我们必要上面的SQL语句:
selecttop100dateadd(d,convert(int,username)-1,min(outdate))asoutdate
fromtable2
groupbyusername
orderbyconvert(int,username)
这里的奇妙在于:
convert(int,username)-1(记得我们指定用户名从1-100:-))
groupbyusername,min(outdate):第一天便可能每一个用户有多个记录。
前往的了局:
outdate
------------------------------------------------------
2001-10-0100:00:00.000
.........
2002-01-0800:00:00.000
b.前往一个一切用户名的记录集:
selectdistinctusernamefromtable2
前往了局:
username
--------------------------------------------------
1
10
100
......
99
c.前往一个100天纪录集和100个用户纪录集的笛卡尔汇合:
select*from
(
selecttop100dateadd(d,convert(int,username)-1,min(outdate))asoutdate
fromtable2
groupbyusername
orderbyconvert(int,username)
)asA
CROSSjoin
(
selectdistinctusernamefromtable2
)asB
orderbyoutdate,convert(int,username)
前往了局100*100条记录:
outdateusername
2001-10-0100:00:00.0001
......
2002-01-0800:00:00.000100
d.前往以后一切用户在数据库的有的记录:
selectoutdate,username,min(cash)ascashfromtable2
groupbyoutdate,username
orderbyoutdate,convert(int,username)
前往记录:
outdateusernamecash
2001-10-0100:00:00.000190
......
2002-01-0800:00:00.00010050
e.将c中前往的笛卡尔集和d中前往的记录做leftjoin:
selectC.outdate,C.username,
D.cash
from
(
select*from
(
selecttop100dateadd(d,convert(int,username)-1,min(outdate))asoutdate
fromtable2
groupbyusername
orderbyconvert(int,username)
)asA
CROSSjoin
(
selectdistinctusernamefromtable2
)asB
)asC
leftjoin
(
selectoutdate,username,min(cash)ascashfromtable2
groupbyoutdate,username
)asD
on(C.username=D.usernameanddatediff(d,C.outdate,D.outdate)=0)
orderbyC.outdate,convert(int,C.username)
注重:用户在当天假如没有记录,cash字段前往NULL,不然cash前往每一个用户当天的余额
outdateusernamecash
2001-10-0100:00:00.000190
2001-10-0100:00:00.0002100
......
2001-10-0200:00:00.000190
2001-10-0200:00:00.0002NULL<--注重这里
......
2002-01-0800:00:00.00010050
f.好了,如今我们最初要做的就是,假如cash为NULL,我们要前往小于以后记录日期的第一个用户余额(因为我们利用orderbycash,以是前往top1记录便可,利用min应当也能够),这个余额即为以后的余额:
caseisnull(D.cash,0)
when0then
(
selecttop1cashfromtable2wheretable2.username=C.username
anddatediff(d,C.outdate,table2.outdate)<0
orderbytable2.cash
)
elseD.cash
endascash
g.最初组合的完全语句就是
selectC.outdate,C.username,
caseisnull(D.cash,0)
when0then
(
selecttop1cashfromtable2wheretable2.username=C.username
anddatediff(d,C.outdate,table2.outdate)<0
orderbytable2.cash
)
elseD.cash
endascash
from
(
select*from
(
selecttop100dateadd(d,convert(int,username)-1,min(outdate))asoutdate
fromtable2
groupbyusername
orderbyconvert(int,username)
)asA
CROSSjoin
(
selectdistinctusernamefromtable2
)asB
)asC
leftjoin
(
selectoutdate,username,min(cash)ascashfromtable2
groupbyoutdate,username
)asD
on(C.username=D.usernameanddatediff(d,C.outdate,D.outdate)=0)
orderbyC.outdate,convert(int,C.username)
前往了局:
outdateusernamecash
2001-10-0100:00:00.000190
2001-10-0100:00:00.0002100
......
2002-01-0800:00:00.00010050
人人看看另有没甚么bug,假如你发明bug大概你有更好的办法,你大概发邮件给我:hydnoahark@netease.com^-^
提供多语言支持,常见的编码如中文的GB2312、BIG5,日文的Shift_JIS等都可以用作数据表名和数据列名。 |
|