在sql server中使用case列过滤sql查询

时间:2016-09-28 16:02:46

标签: sql sql-server

我有这样的查询:

SELECT
  tbl.EmpID,
  CASE
    WHEN emp.status = 'terminated' THEN CONVERT(bit, 1)
    ELSE CONVERT(bit, 0)
  END AS 'Status',
  CASE
    WHEN tbl.LeaveTypeId = 'a' THEN CONVERT(bit, 1)
    ELSE CONVERT(bit, 0)
  END AS 'Absent',
  CASE
    WHEN (tbl.outime IS NULL) AND
      (tbl.LeaveTypeId <> 'a' and tbl.LeaveTypeId Is  null) THEN CONVERT(bit, 1)
    ELSE CONVERT(bit, 0)
  END AS 'InOut',
  emp.EmpFullName,
  tbl.P_Date,
  cmp.cmplogo,
  emp.nation_id,
  emp.dept_id,
  emp.desig_id AS 'designation_id',
  emp.tradecd,
  emp.comp_id,
  emp.section_id,
  emp.location_id,
  emp.emplcatgry
FROM tblattendance tbl
INNER JOIN EMPLOYEEs emp
  ON emp.empid = tbl.empid
INNER JOIN Company cmp
  ON cmp.comp_id = emp.comp_id 
WHERE CONVERT(varchar(10), tbl.p_date, 112) BETWEEN '20160901' AND '20160902'

我的出局就像这样

empid status absent inout
121     1     1      1
122     0      0      0

但只有我想获得状态,缺席,大于0的结果,所以我怎么能写出条件。

3 个答案:

答案 0 :(得分:1)

SELECT S.* FROM ( SELECT   tbl.EmpID,   CASE
     WHEN emp.status = 'terminated' THEN CONVERT(bit, 1)
     ELSE CONVERT(bit, 0)   END AS 'Status',   CASE
     WHEN tbl.LeaveTypeId = 'a' THEN CONVERT(bit, 1)
     ELSE CONVERT(bit, 0)   END AS 'Absent',   CASE
     WHEN (tbl.outime IS NULL) AND
       (tbl.LeaveTypeId <> 'a' and tbl.LeaveTypeId Is  null) THEN CONVERT(bit, 1)
     ELSE CONVERT(bit, 0)   END AS 'InOut',   emp.EmpFullName,   tbl.P_Date,   cmp.cmplogo,   emp.nation_id,   emp.dept_id,  
 emp.desig_id AS 'designation_id',   emp.tradecd,   emp.comp_id,  
 emp.section_id,   emp.location_id,   emp.emplcatgry FROM tblattendance
 tbl INNER JOIN EMPLOYEEs emp   ON emp.empid = tbl.empid INNER JOIN
 Company cmp   ON cmp.comp_id = emp.comp_id  WHERE CONVERT(varchar(10),
 tbl.p_date, 112) BETWEEN '20160901' AND '20160902' )  S WHERE
 S.Status>0  OR S.Absent>0 OR S.InOut>0

答案 1 :(得分:0)

您可以添加如下条件:

WHERE . . . AND
      (emp.status = 'terminated' or tbl.LeaveTypeId = 'a' or
       (tbl.outime IS NULL AND (tbl.LeaveTypeId <> 'a' and tbl.LeaveTypeId Is  null)
      )

或者,您可以使用子查询或CTE来引用SELECT中的列。

编辑:

CTE看起来像

with cte as (<your query here>)
select cte.*
from cte
where status = 1 or absent = 1 or inout = 1;

答案 2 :(得分:0)

使用CROSS APPLY语句尝试VALUES,这允许您重用后续联接中的值,WHERE子句等。

e.g。

SELECT
  tbl.EmpID,
  v.Status,
  v.Absent,
  v.InOut,
  emp.EmpFullName,
  tbl.P_Date,
  cmp.cmplogo,
  emp.nation_id,
  emp.dept_id,
  emp.desig_id AS 'designation_id',
  emp.tradecd,
  emp.comp_id,
  emp.section_id,
  emp.location_id,
  emp.emplcatgry
FROM tblattendance tbl
INNER JOIN EMPLOYEEs emp
  ON emp.empid = tbl.empid
INNER JOIN Company cmp
  ON cmp.comp_id = emp.comp_id 
CROSS APPLY (
  VALUES (
  CASE
    WHEN emp.status = 'terminated' THEN CONVERT(bit, 1)
    ELSE CONVERT(bit, 0)
  END,
  CASE
    WHEN tbl.LeaveTypeId = 'a' THEN CONVERT(bit, 1)
    ELSE CONVERT(bit, 0)
  END,
  CASE
    WHEN (tbl.outime IS NULL) AND
      (tbl.LeaveTypeId <> 'a' and tbl.LeaveTypeId Is  null) THEN CONVERT(bit, 1)
    ELSE CONVERT(bit, 0)
  END
  )
) v (Status, Absent, InOut)
WHERE CONVERT(varchar(10), tbl.p_date, 112) BETWEEN '20160901' AND '20160902'
  AND (v.Status | v.Absent | v.InOut) = 1;

定义v后,您可以像查询中的任何其他表一样使用它。我个人觉得这些比CTE更简单,比子查询更易读。您可以定义依赖于CROSS APPLY上方的表的表达式,然后使用下面任何联接中的值,WHERE子句,GROUP BY等。

另请注意,如果|值中的任何值= 1,则使用BIT(按位或运算符)返回1。