Where子句中的SQL Case语句

时间:2011-02-02 22:02:12

标签: sql sql-server case where

我在2011年1月的201101年,2011年2月的201102年以及20111年的会计期间有一个会计时期表等。
我想在本季度总结一个专栏(eff_cc)。也就是说,我希望获得1月,2月和2月的数据总和。 2011年3月第1季度的日期等等。

所以,我在where子句中使用了Case语句。基本上我说(在where子句中):

  • 如果当前月份是1,4,7或10,那么从该月获取数据;
  • 如果当前月份是2,5,8或11,那么从当前月份获得数据&上个月;和
  • 如果当前月份为3,6,9或12,则从当前和前两个月获取数据

不想工作。代码如下。

select phase_code, accounting_period, sum(eff_cc) as BD_Eff_QTD, 
from prj_detail
where 
    case month(getdate()) % 3
        when  1 then    -- current month is 1,4,7,10
            accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())),2)
        when 2 then     -- current month is 2, 5, 8, 11
            (accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())),2) or 
            accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())-1),2))
        when 3 then     -- current month is 3, 6, 9, 12
            (accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())),2) or 
            accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())-1),2) or
            accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())-2),2))
    end
group by phase_code, accounting_period

4 个答案:

答案 0 :(得分:1)

您可以使用CTE:

(我还假设对所有条目使用交易日期而不是getdate())

CREATE TABLE prj_detail
(phase_code VARCHAR(10)
, transaction_date DATETIME
, eff_cc INT)

INSERT INTO prj_detail
SELECT 'c',GETDATE(),11000
UNION ALL SELECT 'a',GETDATE(),1100
UNION ALL SELECT 'b','01/01/2010',2100
UNION ALL SELECT 'c','01/01/2009',500
UNION ALL SELECT 'a','05/01/2010',7800
UNION ALL SELECT 'b','07/01/2008',6000


WITH PhaseCode (phase_code, accounting_period, eff_cc)

AS 

(SELECT phase_code
,  case month(transaction_date) % 3
        when 1 then    -- current month is 1,4,7,10
            right(Year(transaction_date),4) + Right('0' + rtrim(month(transaction_date)),2)
        when 2 then     -- current month is 2, 5, 8, 11
            right(Year(transaction_date),4) + Right('0' + rtrim(month(transaction_date)-1),2)
        when 3 then     -- current month is 3, 6, 9, 12
            right(Year(transaction_date),4) + Right('0' + rtrim(month(transaction_date)-2),2)
    END accounting_period
, eff_cc
from prj_detail)

SELECT phase_code, accounting_period, SUM(eff_cc) AS BD_Eff_QTD
FROM PhaseCode
GROUP BY phase_code, accounting_period

结果,插入行几次后:

phase_code  accounting_period   BD_Eff_QTD
b   200807  12000
c   200901  1000
b   201001  4200
a   201004  15600
a   201101  13200
c   201101  11000

答案 1 :(得分:1)

感谢所有人提供及时有用的回复(不要屈尊俯就)

我有点根据您的输入设计了一个解决方案。本质上,我创建了一个带有相关数据的子查询和一个新列(Qtr)。此列评估accounting_period,并为每行分配1,2,3或4 然后,我在这个子查询周围包含了另一个选择,其中where子句将'Qtr'与当前季度(来自getDate)进行比较

select phase_code, sum(BD_Eff_QTD) as BD_Eff_QTD
from 
(
select phase_code, accounting_period, sum(eff_pc) as BD_Eff_QTD,
'Qtr' = 
case
when cast (substring(convert(varchar, accounting_period),5,2) as int) <= 3 then 1
when cast (substring(convert(varchar, accounting_period),5,2) as int) <= 6 then 2
when cast (substring(convert(varchar, accounting_period),5,2) as int) <=9 then 3
else 4
end
from prj_detail
group by phase_code, accounting_period
) X
where CurQtr = datepart(qq,getDate()) 
group by phase_code

也许这效率很低,但我每周只运行一次,因此性能不是一个大问题。 再次感谢所有人。

答案 2 :(得分:0)

试试这个(我假设它的SQL Server):

SELECT phase_code, 
       accounting_period, 
       SUM(eff_cc) OVER(PARTITION BY phase_code, yr, qt )AS bd_eff_qtd
  FROM   (SELECT a.*, 
                 CAST(Substring(accounting_period, 1, 4) AS INT)     yr, 
                 (CAST(Substring(accounting_period, 5, 2) AS INT) - 1)/ 3 qt 
          FROM   prj_detail a) a 

e.g:

CREATE TABLE #prj_detail
(
 phase_code VARCHAR(10),
 accounting_period  VARCHAR(10),
 eff_cc INT
)
INSERT INTO #prj_detail
SELECT '1', '201101', 1
UNION
SELECT '1', '201102', 2
UNION
SELECT '1', '201103', 2
UNION
SELECT '1', '201104', 1
UNION
SELECT '1', '201105', 1
UNION
SELECT '1', '201106', 1
UNION
SELECT '1', '201107', 3


SELECT phase_code, 
       accounting_period, 
       SUM(eff_cc) OVER(PARTITION BY phase_code, yr, qt )AS bd_eff_qtd
  FROM   (SELECT a.*, 
                 CAST(Substring(accounting_period, 1, 4) AS INT)     yr, 
                 (CAST(Substring(accounting_period, 5, 2) AS INT) - 1)/ 3 qt 
          FROM   #prj_detail a) a 

答案 3 :(得分:0)

这不是编写CASE语句的正确方法,因为它会返回一个BOOLEAN,它在SQL Server中不能独立存在。只需将它们分成3个OR子句

select phase_code, accounting_period, sum(eff_cc) as BD_Eff_QTD
from prj_detail
where 
(    month(getdate()) % 3 = 1 AND -- current month is 1,4,7,10
    accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())),2))
    OR
(    month(getdate()) % 3 = 2 AND -- current month is 2, 5, 8, 11
    (accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())),2) or 
    accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())-1),2)))
    OR
(    month(getdate()) % 3 = 2 AND -- current month is 3, 6, 9, 12
    (accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())),2) or 
    accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())-1),2) or
    accounting_period = right(Year(getDate()),4) + Right('0' + rtrim(month(getDate())-2),2)))
group by phase_code, accounting_period