case when 1='#' then 1 else 0 end+ case when 2='#' then 1 else 0 end+ ... 以此类推 可以实现 不过每种情况都得写31条...
现把考勤数据合并(unpivot),在用case when 查询。一句也能搞定select name , sum(case when data=' √' then 1 else 0 end )as [出勤], sum(case when data=' #' then 1 else 0 end )as [公休] from ( select * from kaoqin unpivot ( v for c in ([1],[2],[3,[4]) ) u) t group by t.name
use tempdb go if (object_id('tempdb..#1') Is not null) Drop Table #1create table #1(ID int identity,name nvarchar(50),[year] char(4),[month] char(2),[1]nchar(1),[2]nchar(1),[3]nchar(1),[4]nchar(1),[5]nchar(1),[6]nchar(1),[7]nchar(1),[8]nchar(1),[9]nchar(1),[10]nchar(1),[11]nchar(1),[12]nchar(1),[13]nchar(1),[14]nchar(1),[15]nchar(1),[16]nchar(1),[17]nchar(1),[18]nchar(1),[19]nchar(1),[20]nchar(1),[21]nchar(1),[22]nchar(1),[23]nchar(1),[24]nchar(1),[25]nchar(1),[26]nchar(1),[27]nchar(1),[28]nchar(1),[29]nchar(1),[30]nchar(1),[31]nchar(1))insert into #1 ( name,[year],[month],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ) select N'张三','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'√',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√' union all select N'李四','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'∫',N'∫',N'∫',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'Δ',N'Δ',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√'------------------------ declare @tb_sys as table(name nvarchar(50),[sign] nchar(1)) insert into @tb_sys ( name,[sign] ) select N'出勤',N'√' union all select N'迟到',N'∞' union all select N'早退',N'~' union all select N'倒休',N'∧' union all select N'公休',N'#' union all select N'病假',N'∑' union all select N'带薪年假',N'∫' union all select N'事假',N'Δ' ;with cte_unpivot as ( select name,[year],[month],[sign] from #1 a unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b ),cte_count as ( select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count from cte_unpivot a inner join @tb_sys b on b.[sign]=a.[sign] group by a.name,a.[year],a.[month],b.name ) select * From cte_count as a pivot(max(sign_count) for [sign] in ([出勤],[迟到],[早退],[倒休],[公休],[病假],[带薪年假],[事假]))b go /* name year month 出勤 迟到 早退 倒休 公休 病假 带薪年假 事假 李四 2014 7 14 NULL NULL NULL 8 NULL 7 2 张三 2014 7 22 NULL NULL NULL 7 NULL 2 NULL */
这是设计问题,非SQL问题 可能很多人没细想或低估了考勤的细节
下面回答中关于CTE的使用,cte_count ,cte_unpivot这两个结果集,还有],[sign] 定义的是数组吗, 没有看明白 ,能给解释下吗?最好加个注释declare @tb_sys as table(name nvarchar(50),[sign] nchar(1)) insert into @tb_sys ( name,[sign] ) select N'出勤',N'√' union all select N'迟到',N'∞' union all select N'早退',N'~' union all select N'倒休',N'∧' union all select N'公休',N'#' union all select N'病假',N'∑' union all select N'带薪年假',N'∫' union all select N'事假',N'Δ'
;with cte_unpivot as ( select name,[year],[month],[sign] from #1 a unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b ),cte_count as ( select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count from cte_unpivot a inner join @tb_sys b on b.[sign]=a.[sign] group by a.name,a.[year],a.[month],b.name ) select * From cte_count as a pivot(max(sign_count) for [sign] in ([出勤],[迟到],[早退],[倒休],[公休],[病假],[带薪年假],[事假]))b
use tempdb go if (object_id('tempdb..#1') Is not null) Drop Table #1
create table #1(ID int identity,name nvarchar(50),[year] char(4),[month] char(2),[1]nchar(1),[2]nchar(1),[3]nchar(1),[4]nchar(1),[5]nchar(1),[6]nchar(1),[7]nchar(1),[8]nchar(1),[9]nchar(1),[10]nchar(1),[11]nchar(1),[12]nchar(1),[13]nchar(1),[14]nchar(1),[15]nchar(1),[16]nchar(1),[17]nchar(1),[18]nchar(1),[19]nchar(1),[20]nchar(1),[21]nchar(1),[22]nchar(1),[23]nchar(1),[24]nchar(1),[25]nchar(1),[26]nchar(1),[27]nchar(1),[28]nchar(1),[29]nchar(1),[30]nchar(1),[31]nchar(1))
insert into #1 ( name,[year],[month],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ) select N'张三','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'√',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√' union all select N'李四','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'∫',N'∫',N'∫',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'Δ',N'Δ',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√'
-- 1. 使用表变量@tb_sys,描述各种考勤结果符号与名称的关系declare @tb_sys as table(name nvarchar(50),[sign] nchar(1)) insert into @tb_sys ( name,[sign] ) select N'出勤',N'√' union all select N'迟到',N'∞' union all select N'早退',N'~' union all select N'倒休',N'∧' union all select N'公休',N'#' union all select N'病假',N'∑' union all select N'带薪年假',N'∫' union all select N'事假',N'Δ' /* 2.计算过程 ------------------------------------------------------------------------------------------ 2.1 把1-31号的考勤记录进行列转换成行,方便统计各种考勤记录. 对应位置cte_unpivot 分解代码出来如下:
*/ select name,[year],[month],[sign] from #1 a unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b /* 2.2 把2.1的转换结果按[出勤],[迟到],[早退]...[事假] 进行分类汇总,对应位置cte_count 分解代码出来如下: */ ;with cte_unpivot as ( select name,[year],[month],[sign] from #1 a unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b ) select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count from cte_unpivot a inner join @tb_sys b on b.[sign]=a.[sign] group by a.name,a.[year],a.[month],b.name /* 2.3 为了满足原始的需求,[出勤],[迟到],[早退]...[事假]的数据要分列显示,那么对2.2的结果进行行列转换,对应最后的CTE的最后select部分 最终代码如下: */ ;with cte_unpivot as --2.1 ( select name,[year],[month],[sign] from #1 a unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b ),cte_count as --2.2 ( select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count from cte_unpivot a inner join @tb_sys b on b.[sign]=a.[sign] group by a.name,a.[year],a.[month],b.name ) select * --2.3 From cte_count as a pivot(max(sign_count) for [sign] in ([出勤],[迟到],[早退],[倒休],[公休],[病假],[带薪年假],[事假]))b
case when 2='#' then 1 else 0 end+
... 以此类推 可以实现 不过每种情况都得写31条...
sum(case when data=' √' then 1 else 0 end )as [出勤],
sum(case when data=' #' then 1 else 0 end )as [公休]
from
(
select * from kaoqin
unpivot
(
v for c in ([1],[2],[3,[4])
) u) t group by t.name
use tempdb
go
if (object_id('tempdb..#1') Is not null) Drop Table #1create table #1(ID int identity,name nvarchar(50),[year] char(4),[month] char(2),[1]nchar(1),[2]nchar(1),[3]nchar(1),[4]nchar(1),[5]nchar(1),[6]nchar(1),[7]nchar(1),[8]nchar(1),[9]nchar(1),[10]nchar(1),[11]nchar(1),[12]nchar(1),[13]nchar(1),[14]nchar(1),[15]nchar(1),[16]nchar(1),[17]nchar(1),[18]nchar(1),[19]nchar(1),[20]nchar(1),[21]nchar(1),[22]nchar(1),[23]nchar(1),[24]nchar(1),[25]nchar(1),[26]nchar(1),[27]nchar(1),[28]nchar(1),[29]nchar(1),[30]nchar(1),[31]nchar(1))insert into #1 ( name,[year],[month],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] )
select N'张三','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'√',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√'
union all
select N'李四','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'∫',N'∫',N'∫',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'Δ',N'Δ',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√'------------------------
declare @tb_sys as table(name nvarchar(50),[sign] nchar(1))
insert into @tb_sys ( name,[sign] )
select N'出勤',N'√' union all
select N'迟到',N'∞' union all
select N'早退',N'~' union all
select N'倒休',N'∧' union all
select N'公休',N'#' union all
select N'病假',N'∑' union all
select N'带薪年假',N'∫' union all
select N'事假',N'Δ'
;with cte_unpivot as
(
select name,[year],[month],[sign]
from #1 a
unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b
),cte_count as
(
select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count
from cte_unpivot a
inner join @tb_sys b on b.[sign]=a.[sign]
group by a.name,a.[year],a.[month],b.name
)
select *
From cte_count as a
pivot(max(sign_count) for [sign] in ([出勤],[迟到],[早退],[倒休],[公休],[病假],[带薪年假],[事假]))b
go
/*
name year month 出勤 迟到 早退 倒休 公休 病假 带薪年假 事假
李四 2014 7 14 NULL NULL NULL 8 NULL 7 2
张三 2014 7 22 NULL NULL NULL 7 NULL 2 NULL
*/
可能很多人没细想或低估了考勤的细节
没有看明白 ,能给解释下吗?最好加个注释declare @tb_sys as table(name nvarchar(50),[sign] nchar(1))
insert into @tb_sys ( name,[sign] )
select N'出勤',N'√' union all
select N'迟到',N'∞' union all
select N'早退',N'~' union all
select N'倒休',N'∧' union all
select N'公休',N'#' union all
select N'病假',N'∑' union all
select N'带薪年假',N'∫' union all
select N'事假',N'Δ'
;with cte_unpivot as
(
select name,[year],[month],[sign]
from #1 a
unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b
),cte_count as
(
select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count
from cte_unpivot a
inner join @tb_sys b on b.[sign]=a.[sign]
group by a.name,a.[year],a.[month],b.name
)
select *
From cte_count as a
pivot(max(sign_count) for [sign] in ([出勤],[迟到],[早退],[倒休],[公休],[病假],[带薪年假],[事假]))b
use tempdb
go
if (object_id('tempdb..#1') Is not null) Drop Table #1
create table #1(ID int identity,name nvarchar(50),[year] char(4),[month] char(2),[1]nchar(1),[2]nchar(1),[3]nchar(1),[4]nchar(1),[5]nchar(1),[6]nchar(1),[7]nchar(1),[8]nchar(1),[9]nchar(1),[10]nchar(1),[11]nchar(1),[12]nchar(1),[13]nchar(1),[14]nchar(1),[15]nchar(1),[16]nchar(1),[17]nchar(1),[18]nchar(1),[19]nchar(1),[20]nchar(1),[21]nchar(1),[22]nchar(1),[23]nchar(1),[24]nchar(1),[25]nchar(1),[26]nchar(1),[27]nchar(1),[28]nchar(1),[29]nchar(1),[30]nchar(1),[31]nchar(1))
insert into #1 ( name,[year],[month],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] )
select N'张三','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'√',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√'
union all
select N'李四','2014','7',N'√',N'√',N'√',N'∫',N'∫',N'#',N'#',N'∫',N'∫',N'∫',N'∫',N'∫',N'#',N'#',N'√',N'√',N'√',N'Δ',N'Δ',N'#',N'#',N'√',N'√',N'√',N'√',N'√',N'#',N'#',N'√',N'√',N'√'
-- 1. 使用表变量@tb_sys,描述各种考勤结果符号与名称的关系declare @tb_sys as table(name nvarchar(50),[sign] nchar(1))
insert into @tb_sys ( name,[sign] )
select N'出勤',N'√' union all
select N'迟到',N'∞' union all
select N'早退',N'~' union all
select N'倒休',N'∧' union all
select N'公休',N'#' union all
select N'病假',N'∑' union all
select N'带薪年假',N'∫' union all
select N'事假',N'Δ'
/*
2.计算过程
------------------------------------------------------------------------------------------
2.1 把1-31号的考勤记录进行列转换成行,方便统计各种考勤记录. 对应位置cte_unpivot 分解代码出来如下:
*/
select name,[year],[month],[sign]
from #1 a
unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b /*
2.2 把2.1的转换结果按[出勤],[迟到],[早退]...[事假] 进行分类汇总,对应位置cte_count
分解代码出来如下:
*/ ;with cte_unpivot as
(
select name,[year],[month],[sign]
from #1 a
unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b
)
select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count
from cte_unpivot a
inner join @tb_sys b on b.[sign]=a.[sign]
group by a.name,a.[year],a.[month],b.name
/*
2.3 为了满足原始的需求,[出勤],[迟到],[早退]...[事假]的数据要分列显示,那么对2.2的结果进行行列转换,对应最后的CTE的最后select部分
最终代码如下:
*/ ;with cte_unpivot as --2.1
(
select name,[year],[month],[sign]
from #1 a
unpivot( [sign] for [Date] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31] ))b
),cte_count as --2.2
(
select a.name,a.[year],a.[month],b.name as [sign] ,count(b.name) as sign_count
from cte_unpivot a
inner join @tb_sys b on b.[sign]=a.[sign]
group by a.name,a.[year],a.[month],b.name
)
select * --2.3
From cte_count as a
pivot(max(sign_count) for [sign] in ([出勤],[迟到],[早退],[倒休],[公休],[病假],[带薪年假],[事假]))b
with cte as
(
........
)
在sql server查询分析器中,按F1查询联机帮助即可,搜CTE