Where 子句中的 SQL Case 语句

发布于 2024-10-15 18:19:42 字数 1319 浏览 3 评论 0原文

我有一个带有accounting_period的表,其形式为2011年1月的201101,2011年2月的201102,等等。
我正在尝试对本季度的一列 (eff_cc) 进行求和。也就是说,我想获得一月、二月和二月的数据总和。 Mar 2011 表示第一季度的日期等。

因此,我在 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

I have a table with accounting_period in the form of 201101 for Jan 2011, 201102 for Feb 2011, etc.

I am trying to sum a column (eff_cc) for the quarter. That is, I want to get the sum the data for Jan, Feb & Mar 2011 for a date in the 1st quarter, etc.

So, I used a Case statement in the where clause. Basically I said (in the where clause) that:

  • if the current month is 1,4,7 or 10, then get data from that month;
  • if the current month is 2,5,8 or 11, then get the data from the curent month & the previous month; and
  • if the current month is 3,6,9, or 12 then get data from the current and the previous two months

Doesn't want to work. The code is below.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一城柳絮吹成雪 2024-10-22 18:19:42

您可以为此使用 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

You could use CTE for this:

(I also made an assumption of using a transaction date instead of getdate() for all entries)

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

Results, after inserting the rows a few times:

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
浮萍、无处依 2024-10-22 18:19:42

感谢你们所有人的及时和有用的回复(没有居高临下),

我根据你们的意见设计了一个解决方案。本质上,我创建了一个包含相关数据的子查询和一个新列 (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

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

Thanks to all of you for the prompt and useful responses (without being condescending)

I kinda devised a solution based on your input. In essence, I created a subquery, with the relevant data, and a new column (Qtr). This column evaluates the accounting_period, and assigns 1,2,3 or 4 to each row.
Then, I wrapped another select around this subquery, with a where clause comparing the 'Qtr' to the current quarter (from 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

Maybe this is inefficient, but I run this only once a week, so performance is not a big issue.
Thanks again to all.

晌融 2024-10-22 18:19:42

这不是编写 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

That is not the right way to write a CASE statement, as it is, it returns a BOOLEAN, which in SQL Server cannot stand alone. Just split them into 3 OR clauses

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
情深缘浅 2024-10-22 18:19:42

试试这个(我假设它是 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 

例如:

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 

Try this(I assume its 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 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文