sql經典面試題
group by
create table teacher(teacher nvarchar(10),teach_day int,teach_desc nchar(1));
insert into teacher values('老師1',2,'有')
insert into teacher values('老師1',3,'有')
insert into teacher values('老師1',3,'有')
insert into teacher values('老師2',2,'無')
insert into teacher values('老師2',2,'有')
insert into teacher values('老師2',1,'有')
insert into teacher values('老師3',1,'有')
insert into teacher values('老師3',3,'無')
teacher teach_day teach_desc
老師1 2 有
老師1 3 有
老師1 3 有
老師2 2 無
老師2 2 有
老師2 1 有
老師3 1 有
老師3 3 無
Result:
teacher monday tuesday wednesday
老師1 0 1 2
老師2 1 1 0
老師3 1 0 0
select teacher,
sum(case when teach_day=1 then 1 else 0 end)'monday',
sum(case when teach_day=2 then 1 else 0 end)'tuesday',
sum(case when teach_day=3 then 1 else 0 end)'wednesday'
from teacher where teach_desc='有' group by teacher
Linq:
from t in Teachers
where t.Teach_desc=='有'
group t by t.Content into g
select new{
teacher=g.Key,
monday=g.Sum(s=>s.Teach_day==1?1:0),
tuesday=g.Sum(s=>s.Teach_day==2?1:0),
wednesday=g.Sum(s=>s.Teach_day==3?1:0)
}
對年月日分組查詢,統計每月每天每年的活躍人數,根據登陸日期
create table logininfo(name varchar(50),logindate datetime)
insert into logininfo values('dnadan',getdate())
insert into logininfo values('c','2017/9/21 7:58:05')
insert into logininfo values('d','2017/9/20 0:58:05')
insert into logininfo values('c','2017/9/21 10:58:05')
insert into logininfo values('d','2017/9/20 12:58:05')
insert into logininfo values('e','2017/9/19 23:58:05')
insert into logininfo values('f','2017/9/20 20:58:05')
insert into logininfo values('g','2017/9/21 20:58:05')
insert into logininfo values('h','2015/9/19 20:58:05')
insert into logininfo values('i','2014/9/20 20:58:05')
insert into logininfo values('j','2016/9/21 20:58:05')
統計每天的登陸人數
select convert(date,logindate)date,count(*) from logininfo group by convert(date,logindate);
Linq:
from l in Logininfos
group l by l.Logindate.Value.Date into g
select new{date=g.Key,sum=g.Count()}
統計每月登陸人數
select convert(varchar(7),logindate,126),count(*) from logininfo group by convert(varchar(7),logindate,126)
Linq:
from l in Logininfos
group l by l.Logindate.Value.Year+"/"+(l.Logindate.Value.Month<10?"0":"")+l.Logindate.Value.Month into g
select new{date=g.Key,sum=g.Count()}
這里應該使用拼接,這樣可以減少對子查詢的嵌套查詢
臨時表和全局臨時表
5.在sqlserver2000中請用sql創建一張用戶臨時表和系統臨時表,里面包含兩個字段ID和IDValues,類型都是int型,並解釋下兩者的區別?
------------------------------------------
用戶臨時表:create table #xx(ID int, IDValues int)
系統臨時表:create table ##xx(ID int, IDValues int)
區別:
用戶臨時表只對創建這個表的用戶的Session可見,對其他進程是不可見的.
當創建它的進程消失時這個臨時表就自動刪除.
全局臨時表對整個SQL Server實例都可見,但是所有訪問它的Session都消失的時候,它也自動刪除.
使用Left Join 拼接出結果
dept_yeji
mon dep yj
-------------------------------
一月份 01 10
一月份 02 10
一月份 03 5
二月份 02 8
二月份 04 9
三月份 03 8
dept
dep dname
--------------------------------
01 國內業務一部
02 國內業務二部
03 國內業務三部
04 國際業務部
result
dep 一月份 二月份 三月份
--------------------------------------
01 10 null null
02 10 8 null
03 5 null 8
04 null 9 null
create table dept_yeji(mon varchar(10),dep varchar(2),yj int)
create table dept(dep varchar(2),dname varchar(20))
insert into dept_yeji values('一月份','01',10)
insert into dept_yeji values('一月份','02',10)
insert into dept_yeji values('一月份','03',5)
insert into dept_yeji values('二月份','02',8)
insert into dept_yeji values('二月份','04',9)
insert into dept_yeji values('三月份','03',8)
insert into dept values('01','國內業務一部')
insert into dept values('02','國內業務二部')
insert into dept values('03','國內業務三部')
insert into dept values('04','國內業務部')
select a.dep,b.yj '一月份',c.yj '二月份',d.yj '三月份'
from dept a
left join dept_yeji b on a.dep=b.dep and b.mon='一月份'
left join dept_yeji c on a.dep=c.dep and c.mon='二月份'
left join dept_yeji d on a.dep=d.dep and d.mon='三月份'
Linq:
from a in Depts
join b in Dept_yejis on new{a.Dep,Mon="一月份"} equals new{b.Dep,b.Mon} into bs
from b in bs.DefaultIfEmpty()
join c in Dept_yejis on new{a.Dep,Mon="二月份"} equals new{c.Dep,c.Mon} into cs
from c in cs.DefaultIfEmpty()
join d in Dept_yejis on new{a.Dep,Mon="三月份"} equals new{d.Dep,d.Mon} into ds
from d in ds.DefaultIfEmpty()
select new{
a.Dep,
first=b.Yj,
second=c.Yj,
thired=d.Yj
}
綜合使用
payrec
fcr_id fcr_date rank fcr_busType fcr_curr fcr_amount
1 2016-03-22 00:00:00.000 銷售家具 收 cny 720
2 2015-01-12 00:00:00.000 銷售家具 收 cny 12090
3 2015-01-12 00:00:00.000 支付房租 付 cny -9091
4 2015-01-12 00:00:00.000 紅星轉賬 收 cny 100000
5 2015-01-12 00:00:00.000 購買家具100件 付 cny -10918
6 2015-01-12 00:00:00.000 購買家具30件 付 cny -4069
7 2015-01-14 00:00:00.000 購買家具150件 付 cny -20884
8 2015-01-14 11:00:00.000 購買家具100件 付 cny -10394
9 2015-01-14 10:00:00.000 銷售家具 收 cny 39800
10 2015-01-14 00:00:00.000 支付欠款 付 cny -8800
11 2015-01-14 00:00:00.000 支付欠款 付 cny -40000
12 2015-01-15 00:00:00.000 紅星轉賬 收 cny 710
13 2015-01-15 00:00:00.000 紅星轉賬 收 cny 810
14 2015-01-15 00:00:00.000 紅星轉賬 收 cny 13010
15 2015-01-15 00:00:00.000 紅星轉賬 收 cny 3800
統計結果
1 2015-01-12 00:00:00.000 12090 12090
2 2015-01-12 00:00:00.000 -9091 2999
3 2015-01-12 00:00:00.000 100000 102999
4 2015-01-12 00:00:00.000 -10918 92081
5 2015-01-12 00:00:00.000 -4069 88012
6 2015-01-14 00:00:00.000 -20884 67128
7 2015-01-14 00:00:00.000 -8800 58328
8 2015-01-14 00:00:00.000 -40000 18328
9 2015-01-14 10:00:00.000 39800 58128
10 2015-01-14 11:00:00.000 -10394 47734
11 2015-01-15 00:00:00.000 710 48444
12 2015-01-15 00:00:00.000 810 49254
13 2015-01-15 00:00:00.000 13010 62264
14 2015-01-15 00:00:00.000 3800 66064
15 2016-03-22 00:00:00.000 720 66784
需要使用到臨時表 和 row_num() over (order by xxx) 和 case when
create table payrec(
fcr_id int identity(1,1),
fcr_date datetime,
fcr_remark varchar(20),
fcr_busType varchar(2),
fcr_curr varchar(5),
fcr_amount decimal
)
insert into payrec values
('2016/3/22','銷售家具','收','cny',720), -- 這里故意放了一條時間靠后的記錄在這里,是為了用fcr_date來排序,可以用臨時表先排序
('2015/1/12','銷售家具','收','cny',12090),
('2015/1/12','支付房租','付','cny',-9090.84),
('2015/1/12','紅星轉賬','收','cny',100000),
('2015/1/12','購買家具100件','付','cny',-10917.68),
('2015/1/12','購買家具30件','付','cny',-4069.22),
('2015/1/14','購買家具150件','付','cny',-20883.55),
('2015/1/14 11:00','購買家具100件','付','cny',-10394.44),
('2015/1/14 10:00','銷售家具','收','cny',39800),
('2015/1/14','支付欠款','付','cny',-8800),
('2015/1/14','支付欠款','付','cny',-40000),
('2015/1/15','紅星轉賬','收','cny',710),
('2015/1/15','紅星轉賬','收','cny',810),
('2015/1/15','紅星轉賬','收','cny',13010),
('2015/1/15','紅星轉賬','收','cny',3800)
create procedure query_fcr
as
begin
select rowid=row_number() over (order by fcr_date),* into #payrec from payrec ; -- 臨時表存儲排序結果
select rowid,fcr_date ,
(case when fcr_amount >0 then str(fcr_amount) else '' end) '收',
(case when fcr_amount<0 then str(fcr_amount) else '' end) '付',
'余額'=(select sum(fcr_amount) from #payrec where rowid<=a.rowid) from #payrec a
end
select * from payrec
exec query_fcr