菠菜源码-下载复合枚举在SQL Server中的应用

状态字段,菠菜源码-下载Q2152876294 论坛:diguaym.com 一般是单纯的, 但如果有复合的状态怎么办?

比如考勤, 一个人一天之中, 既有迟到, 又有早退, 那如何设计这个状态字段?

用户考勤, 共 6 种状态:

--userState:
--1 出勤 1
--2 请假 10
--4 公差 100
--8 迟到 1000
--16 早退 10000
--32 旷工 100000
如上, 设计成 二进制对应的值, 前面是 1, 后面全是 0, 而且位置全部错开, 这样相加时, 绝对不会有重合的问题出现。

--如果需要组合:
--既有 迟到,也有早退
--SELECT 8 | 16
/
24
/
那这种字段的值, 到时候如何查询出是哪几种组合?

USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
GO
CREATE TABLE t(
id INT IDENTITY(1,1) PRIMARY KEY,
userId INT NOT NULL,
addinsDate DATE NOT NULL,
seg INT, --班次时段 0 上午 1 下午 2 晚上
userState INT, --1 出勤 2 请假 4 公差 8 迟到 16 早退 32 旷工
userStateSplit AS
CASE WHEN userState IN (1,2,4,8,16,32) THEN LTRIM(userState)
WHEN userState = 3 THEN '1,2'
WHEN userState = 5 THEN '1,4'
WHEN userState = 9 THEN '1,8'
WHEN userState = 17 THEN '1,16'
WHEN userState = 33 THEN '1,32'
WHEN userState = 6 THEN '2,4'
WHEN userState = 10 THEN '2,8'
WHEN userState = 18 THEN '2,16'
WHEN userState = 34 THEN '2,32'
WHEN userState = 12 THEN '4,8'
WHEN userState = 20 THEN '4,16'
WHEN userState = 36 THEN '4,32'
WHEN userState = 24 THEN '8,16'
WHEN userState = 40 THEN '8,32'
WHEN userState = 48 THEN '16,32'
WHEN userState = 7 THEN '1,2,4'
WHEN userState = 11 THEN '1,2,8'
WHEN userState = 19 THEN '1,2,16'
WHEN userState = 35 THEN '1,2,32'
WHEN userState = 13 THEN '1,4,8'
WHEN userState = 21 THEN '1,4,16'
WHEN userState = 37 THEN '1,4,32'
WHEN userState = 25 THEN '1,8,16'
WHEN userState = 41 THEN '1,8,32'
WHEN userState = 49 THEN '1,16,32'
WHEN userState = 14 THEN '2,4,8'
WHEN userState = 22 THEN '2,4,16'
WHEN userState = 38 THEN '2,4,32'
WHEN userState = 26 THEN '2,8,16'
WHEN userState = 42 THEN '2,8,32'
WHEN userState = 50 THEN '2,16,32'
WHEN userState = 28 THEN '4,8,16'
WHEN userState = 44 THEN '4,8,32'
WHEN userState = 52 THEN '4,16,32'
WHEN userState = 56 THEN '8,16,32'
WHEN userState = 15 THEN '1,2,4,8'
WHEN userState = 23 THEN '1,2,4,16'
WHEN userState = 39 THEN '1,2,4,32'
WHEN userState = 29 THEN '1,4,8,16'
WHEN userState = 45 THEN '1,4,8,32'
WHEN userState = 57 THEN '1,8,16,32'
WHEN userState = 30 THEN '2,4,8,16'
WHEN userState = 46 THEN '2,4,8,32'
WHEN userState = 58 THEN '2,8,16,32'
WHEN userState = 60 THEN '4,8,16,32'
WHEN userState = 31 THEN '1,2,4,8,16'
WHEN userState = 47 THEN '1,2,4,8,32'
WHEN userState = 61 THEN '1,4,8,16,32'
WHEN userState = 63 THEN '1,2,4,8,16,32'
END
)
GO
INSERT INTO t VALUES (1,'2018-08-01',0,1)
INSERT INTO t VALUES (1,'2018-08-01',1,1)
INSERT INTO t VALUES (1,'2018-08-02',0,2)
INSERT INTO t VALUES (1,'2018-08-02',0,1)
INSERT INTO t VALUES (2,'2018-08-02',0,24)
GO
SELECT
userId
,addinsDate
,SUM(CASE WHEN ','+userStateSplit+',' LIKE '%,1,%' THEN 1 ELSE 0 END) AS [出勤]
,SUM(CASE WHEN ','+userStateSplit+',' LIKE '%,2,%' THEN 1 ELSE 0 END) AS [请假]
,SUM(CASE WHEN ','+userStateSplit+',' LIKE '%,4,%' THEN 1 ELSE 0 END) AS [公差]
,SUM(CASE WHEN ','+userStateSplit+',' LIKE '%,8,%' THEN 1 ELSE 0 END) AS [迟到]
,SUM(CASE WHEN ','+userStateSplit+',' LIKE '%,16,%' THEN 1 ELSE 0 END) AS [早退]
,SUM(CASE WHEN ','+userStateSplit+',' LIKE '%,32,%' THEN 1 ELSE 0 END) AS [旷工]
FROM t
GROUP BY userId,addinsDate

根据 mingqing6364 兄的评论, 改了一下, 现在非常完美了, 用计算列比较简洁轻松, 不用计算列也能得到结果:

USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
GO
CREATE TABLE t(
id INT IDENTITY(1,1) PRIMARY KEY,
userId INT NOT NULL,
addinsDate DATE NOT NULL,
seg INT, --班次时段 0 上午 1 下午 2 晚上
userState INT, --1 出勤 2 请假 4 公差 8 迟到 16 早退 32 旷工
userStateSplit AS
STUFF((
CASE WHEN userState & 1 = 1 THEN ',1' ELSE '' END
+
CASE WHEN userState & 2 = 2 THEN ',2' ELSE '' END
+
CASE WHEN userState & 4 = 4 THEN ',4' ELSE '' END
+
CASE WHEN userState & 8 = 8 THEN ',8' ELSE '' END
+
CASE WHEN userState & 16 = 16 THEN ',16' ELSE '' END
+
CASE WHEN userState & 32 = 32 THEN ',32' ELSE '' END
),1,1,'')
)
GO
INSERT INTO t VALUES (1,'2018-08-01',0,1)
INSERT INTO t VALUES (1,'2018-08-01',1,1)
INSERT INTO t VALUES (1,'2018-08-02',0,2)
INSERT INTO t VALUES (2,'2018-08-02',0,48)
INSERT INTO t VALUES (2,'2018-08-02',0,24)
GO
SELECT * FROM t

SELECT
userId
,addinsDate
,SUM(CASE WHEN userState & 1 = 1 THEN 1 ELSE 0 END) AS [出勤]
,SUM(CASE WHEN userState & 2 = 2 THEN 1 ELSE 0 END) AS [请假]
,SUM(CASE WHEN userState & 4 = 4 THEN 1 ELSE 0 END) AS [公差]
,SUM(CASE WHEN userState & 8 = 8 THEN 1 ELSE 0 END) AS [迟到]
,SUM(CASE WHEN userState & 16 = 16 THEN 1 ELSE 0 END) AS [早退]
,SUM(CASE WHEN userState & 32 = 32 THEN 1 ELSE 0 END) AS [旷工]
FROM t
GROUP BY userId,addinsDate

猜你喜欢

转载自blog.51cto.com/13951509/2169332
今日推荐