【问题标题】:How to write two case statements with in case如何用 in case 写两个 case 语句
【发布时间】:2016-07-05 07:42:35
【问题描述】:

我的查询显示错误,谁能帮助我。

我的查询:

SELECT     A.EmpCodeC, 
           E.EmpNameC, 
           B.DesigNameC, 
           C.DeptNameC, 
           D.SecNameC, 
           A.ClockDateD, 
           TimeClk1N, 
           TimeClk2N, 
           TimeClk3N, 
           TimeClk4N, 
           A.BJClk1N, 
           A.BJClk2N, 
           A.BJClk3N, 
           A.BJClk4N, 
           A.TimeInN, 
           A.TimeOutN, 
           A.ShiftCodeC, 
           A.NormalN, 
           A.ActlWrkHrsN, 
           A.LatenessN, 
           A.UnderN, 
           A.OT10N, 
           A.OT15N, 
           A.OT20N, 
           A.OT30N, 
           A.SflatN, 
           A.ShiftAllN, 
           A.MealAllN, 
           A.TranAllN, 
           A.Oth1AllN, 
           A.Oth2AllN, 
           A.HealthAllN, 
           A.AttdAllN, 
           A.ReaCodeC, 
           A.SplReaCodeC, 
           Isnull(I.PayTypeC, '') PayType, 
           E.BasicSalaryN, 
           CASE 
                      WHEN Datename(dw, A.ClockDateD)='Sunday' THEN 
                                 CASE 
                                            WHEN A.OT20N >4 THEN ((E.BasicSalaryN/(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2))/9)* (4+A.OT10N+A.OT20N+ A.OT30N))
                                            ELSE ((E.BasicSalaryN                /(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2) )/9)* (A.OT10N+A.OT15N+ A.OT20N+ A.OT30N))
                                 END AS OT_Amnt, 
                                 CASE 
                                            WHEN A.OT20N >4 THEN ((E.BasicSalaryN/(SubString(CAST(EOMONTH ( A.ClockDateD ) AS VARCHAR(20)),9,2))/9)* (A.OT15N-4)) 
                                            ELSE ('0.00') 
                                 END AS Insentive_Amnt 
                      ELSE '0.00' OT_Amnt '0.00' Insentive_Amnt 
           END 
FROM       Daily A 
INNER JOIN TMSStrt.DBO.Designation B 
ON         A.DesigCodeC = B.DesigCodeC 
INNER JOIN TMSStrt.DBO.Department C 
ON         A.DeptCodeC = C.DeptCodeC 
INNER JOIN TMSStrt.DBO.Section D 
ON         A.SecCodeC = D.SecCodeC 
AND        D.DeptCodeC = C.DeptCodeC 
INNER JOIN StaffMaster E 
ON         A.EmpCodeC = E.EmpCodeC 
LEFT JOIN  TMSStrt.DBO.Reason I 
ON         A.ReaCodeC = I.ReasonCodeC 
WHERE      A.ClockDateD >= '01-07-2016' 
AND        A.ClockDateD <= '04-07-2016' 
ORDER BY   E.EmpNameC, 
           A.ClockDateD

【问题讨论】:

  • 请修正您的格式。每个可见宽度一行代码,并缩进 4 个空格以使文本等宽。
  • 发布大量文本并说它“显示错误”,但没有说明这些错误是什么,它们发生在哪一行,更重要的是,您实际尝试实现的目标不太可能征求积极的意见回复。按照已经要求格式化您的代码,确定导致错误的特定部分,描述您正在尝试做什么,然后有人可能会帮助您。

标签: sql-server


【解决方案1】:

好的,看看你目前的情况 - 你的查询有点错误。 首先,您嵌套的所有 case 语句(顺便说一句,这不起作用)具有完全相同的行为?我认为他们应该是如下

案例陈述:

      CASE 
        WHEN Datename(dw, A.ClockDateD)='Sunday' AND A.OT20N >4 
        THEN ((E.BasicSalaryN/(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2))/9)* (4+A.OT10N+A.OT20N+ A.OT30N))
        ELSE ((E.BasicSalaryN/(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2) )/9)* (A.OT10N+A.OT15N+ A.OT20N+ A.OT30N))
      END AS OT_Amnt


     CASE 
       WHEN Datename(dw, A.ClockDateD)='Sunday' WHEN A.OT20N >4 
       THEN ((E.BasicSalaryN/(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2))/9)* (4+A.OT10N+A.OT20N+ A.OT30N))
       ELSE ((E.BasicSalaryN/(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2) )/9)* (A.OT10N+A.OT15N+ A.OT20N+ A.OT30N))
     END AS Insentive_Amnt,

完全删除了嵌套,只需调用两个单独的 case 语句,使用 MSSQL,复制 case 语句的开销可以忽略不计

如果您想保留嵌套的想法,您将需要转换为存储过程。在那里,您可以使用 if 语句设置一个变量,然后在 if 语句中调用您的 case 语句。

据我所知,虽然您不需要存储过程。另一个注释

ELSE '0.00' OT_Amnt '0.00' Insentive_Amnt

我不知道这是什么,但它永远不会工作,如果您尝试连接某些内容,您需要根据数据类型使用 & 或 + 语法。

【讨论】:

  • 如果 datename 不是星期日,两个 CASE 表达式都会返回错误的结果,它应该是 0。如果 A.OT20N &lt;= 4,第二个 CASE 也应该返回 0。我也想过删除嵌套,但我必须重复测试 datename 是否为 Sunday,而且我不确定哪一个实际上表现最好(这将取决于数据)
  • 如果是这种情况,我会说使用带有 IF 语句块的存储过程。
  • 在这种情况下存储过程有什么帮助?这是单个查询,您不能从查询中调用存储过程。您是否正在考虑表值函数和 CROSS APPLY?我认为最好的方法是 CASE 表达式(嵌套或展平)
  • 我不会在语句中使用存储过程。我会将整个查询转换为语句,然后使用该存储过程返回整个数据集。如果您想像现在这样进行嵌套调用,您别无选择。您有两个选择,两个单独的 Case 语句或带有 IF 语句的存储过程
  • 我仍然看不到存储过程有什么帮助。 IF 条件必须对查询中的每一行应用一次。您必须运行 2 个相同的查询,将条件放在 WHERE 中并合并结果,或者使用具有相同条件的 2 个 CASE 表达式。 IF 适用于单个值(即单个记录)。请您提供一个示例,说明如何在存储过程中使用 IF 来实现所需的结果?
【解决方案2】:

您的外部 CASE 是错误的。 Yo 不能从 CASE 内部返回两列,只能返回一个值。所以你可以写:

       ...
       CASE 
           WHEN Datename(dw, A.ClockDateD)='Sunday' THEN 
               CASE 
                   WHEN A.OT20N >4 THEN ((E.BasicSalaryN/(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2))/9)* (4+A.OT10N+A.OT20N+ A.OT30N))
                   ELSE ((E.BasicSalaryN                /(Substring(Cast(Eomonth ( A.ClockDateD ) AS VARCHAR(20)),9,2) )/9)* (A.OT10N+A.OT15N+ A.OT20N+ A.OT30N))
               END 
           ELSE 0.0 
       END AS OT_Amnt,
       CASE 
           WHEN Datename(dw, A.ClockDateD)='Sunday' AND A.OT20N >4 THEN ((E.BasicSalaryN/(SubString(CAST(EOMONTH ( A.ClockDateD ) AS VARCHAR(20)),9,2))/9)* (A.OT15N-4)) 
           ELSE 0.0
       END AS Insentive_Amnt,
       ...

还要小心那些日期到 varchar CAST、SUBSTRING 以及在算术中混合数字和字符串数据。最好使用日期函数(例如:Year(EOMONTH ( A.ClockDateD ))-2000 而不是(SubString(CAST(EOMONTH ( A.ClockDateD ) AS VARCHAR(20)),9,2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多