国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

關于論壇上那個SQL微軟面試題。我的解答方法 :-)

2024-07-21 02:08:57
字體:
來源:轉載
供稿:網友

問題:

一百個賬戶各有100$,某個賬戶某天如有支出則添加一條新記錄,記錄其余額。一百天后,請輸出每天所有賬戶的余額信息
 

這個問題的難點在于每個用戶在某天可能有多條紀錄,也可能一條紀錄也沒有(不包括第一天)

返回的記錄集是一個100天*100個用戶的紀錄集

下面是我的思路:

1.創建表并插入測試數據:我們要求username從1-100
create table [dbo].[table2] (
[username] [varchar] (50) not null , --用戶名
[outdate] [datetime] not null , --日期
[cash] [float] not null --余額
) on [primary

declare @i int
set @i=1
while @i<=100
  begin
    insert table2 values(convert(varchar(50),@i),'2001-10-1',100)
    insert table2 values(convert(varchar(50),@i),'2001-11-1',50)
    set @[email protected]+1
  end
insert table2 values(convert(varchar(50),@i),'2001-10-1',90)

select * from table2 order by outdate,convert(int,username)

2.組合查詢語句:
a.我們必須返回一個從第一天開始到100天的紀錄集:
如:2001-10-1(這個日期是任意的) 到 2002-1-8
由于第一天是任意一天,所以我們需要下面的sql語句:
select top 100 dateadd(d,convert(int,username)-1,min(outdate)) as outdate
from table2
group by username
order by convert(int,username)
這里的奧妙在于:
convert(int,username)-1(記得我們指定用戶名從1-100 :-))
group by username,min(outdate):第一天就可能每個用戶有多個紀錄。
返回的結果:
outdate                                               
------------------------------------------------------
2001-10-01 00:00:00.000
.........
2002-01-08 00:00:00.000

b.返回一個所有用戶名的紀錄集:
select distinct username from table2
返回結果:
username                                         
--------------------------------------------------
1
10
100
......
99

c.返回一個100天記錄集和100個用戶記錄集的笛卡爾集合:
select * from
(
select top 100 dateadd(d,convert(int,username)-1,min(outdate)) as outdate
from table2
group by username
order by convert(int,username)
) as a
cross join
(
select distinct username from table2
) as b
order by outdate,convert(int,username)
返回結果100*100條紀錄:
outdate                            username
2001-10-01 00:00:00.000            1
......
2002-01-08 00:00:00.000            100

d.返回當前所有用戶在數據庫的有的紀錄:
select outdate,username,min(cash) as cash from table2
group by outdate,username

order by outdate,convert(int,username)
返回紀錄:
outdate                            username    cash
2001-10-01 00:00:00.000            1          90
......
2002-01-08 00:00:00.000            100        50

e.將c中返回的笛卡爾集和d中返回的紀錄做left join:
select c.outdate,c.username,
d.cash
from
(
select * from
(
select top 100 dateadd(d,convert(int,username)-1,min(outdate)) as outdate
from table2
group by username
order by convert(int,username)
) as a
cross join
(
select distinct username from table2
) as b
) as c
left join
(
select outdate,username,min(cash) as cash from table2
group by outdate,username
) as d
on(c.username=d.username and datediff(d,c.outdate,d.outdate)=0)

order by c.outdate,convert(int,c.username)
注意:用戶在當天如果沒有紀錄,cash字段返回null,否則cash返回每個用戶當天的余額
outdate                            username    cash
2001-10-01 00:00:00.000            1          90
2001-10-01 00:00:00.000            2          100
......
2001-10-02 00:00:00.000            1          90
2001-10-02 00:00:00.000            2          null  <--注意這里
......

2002-01-08 00:00:00.000            100        50

f.好了,現在我們最后要做的就是,如果cash為null,我們要返回小于當前紀錄日期的第一個用戶余額(由于我們使用order by cash,所以返回top 1紀錄即可,使用min應該也可以),這個余額即為當前的余額:
case isnull(d.cash,0)
when 0 then
(
select top 1 cash from table2 where table2.username=c.username
and datediff(d,c.outdate,table2.outdate)<0
order by table2.cash
)
else d.cash
end as cash

g.最后組合的完整語句就是
select c.outdate,c.username,
case isnull(d.cash,0)
when 0 then
(
select top 1 cash from table2 where table2.username=c.username
and datediff(d,c.outdate,table2.outdate)<0
order by table2.cash
)
else d.cash
end as cash
from
(
select * from
(
select top 100 dateadd(d,convert(int,username)-1,min(outdate)) as outdate
from table2
group by username
order by convert(int,username)
) as a
cross join
(
select distinct username from table2
) as b
) as c
left join
(
select outdate,username,min(cash) as cash from table2
group by outdate,username
) as d
on(c.username=d.username and datediff(d,c.outdate,d.outdate)=0)

order by c.outdate,convert(int,c.username)

返回結果:
outdate                                 username        cash
2001-10-01 00:00:00.000    1                    90
2001-10-01 00:00:00.000    2                   100
......
2002-01-08 00:00:00.000    100                50

大家看看還有沒什么bug,如果你發現bug或者你有更好的方法,你可能發郵件給我:[email protected] ^-^

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 祥云县| 南岸区| 个旧市| 政和县| 临江市| 青岛市| 乌拉特中旗| 汝城县| 金堂县| 濉溪县| 汾阳市| 厦门市| 广灵县| 凤凰县| 当涂县| 双桥区| 旬邑县| 嘉荫县| 虞城县| 靖安县| 西青区| 奈曼旗| 镇安县| 伊通| 开封市| 昌宁县| 稻城县| 加查县| 临桂县| 绍兴市| 武安市| 若尔盖县| 宜昌市| 清苑县| 招远市| 巴南区| 竹山县| 闽清县| 泰来县| 瑞金市| 邵阳县|