简体   繁体   English

使用多个CASE语句时出错[SQL]

[英]Errors when using multiple CASE statements [SQL]

Using SQL in Microsoft SQL Server, I have a very specific problem where I am comparing data between two months. 在Microsoft SQL Server中使用SQL时,我遇到了一个非常具体的问题,即我要比较两个月之间的数据。 This data can either have one of two status' - to keep it simple it's either "1" or "0" or basically "yes" or "no." 此数据可以具有两种状态之一-为简单起见,它可以是“ 1”或“ 0”,或者基本上是“是”或“否”。

I'd like to consider the following scenarios: 我想考虑以下情况:

  • if a row has status of "1" in one month and that changes to "0" the next month and vice versa 如果某行在一个月内的状态为“ 1”,而在下个月变为“ 0”, 反之亦然
  • if the status hasn't changed from one month to another (ie "1" to "1" or "0" to "0") 如果状态没有从一个月更改为另一个月(即“ 1”更改为“ 1”或“ 0”更改为“ 0”)
  • if value for status was null in previous month and changes to either "1" or "0" the next 如果状态值在上个月为空,并且在下个月更改为“ 1”或“ 0”

I assume I can use multiple CASE statements for this and what I have so far is the following until I get stuck: 我假设我可以为此使用多个CASE语句,到目前为止,在遇到问题之前,我得到的是以下内容:

select
     --determine if status changes from 1 to 0 between two months or stays the same
     case
     when T.[status] = '1' and T.date between '01-01-2017' and '02-28-2017'
     then 'No Change'
     else
     'Status Changed to 0'
     end,

     --determine if status changes from 0 to 1 between two months or stays the same
     case
     when T.[status] = '0' and T.date between '01-01-2017' and '02-28-2017'
     then 'No Change'
     else 
     'Status Changed to 1'
     end,

     --determine if there was new row that didn't appear in first month with a status of 1 or 0 in second month
     case
     when T.status is null in T.date between '01-01-2017' and '01-31-2017'  
     and T.status = '1' in T.date between '02-01-2017' and '02-28-2017' then 'New Status to 1'
     else
     'New Status of 1'
     end, *
from table T
where ....

This code is working for the first CASE statement to display a status change from 1 to 0 in a new column but its making another column for the second status and I am not sure if it is working as I intend it to. 该代码适用于第一个CASE语句,以在新列中显示从1到0的状态更改,但是它使第二列显示另一状态,因此我不确定它是否按预期工作。 Moreover, since I am examining the two months together, I can't seem to logic my way around coding the other scenarios into my SQL. 而且,由于我正在一起检查两个月,因此我似乎无法逻辑地将其他方案编码到我的SQL中。

I'm trying to find some way to condense all of the CASE statements to only producing one extra column and another problem I am having is that the third CASE statement is throwing a syntax error at the first "IN." 我试图找到一种方法来压缩所有CASE语句,使其仅产生一个额外的列,而我遇到的另一个问题是,第三条CASE语句在第一个“ IN”处引发了语法错误。 Hope this makes sense to someone and thanks in advance for any input or tips you can provide. 希望这对某人有意义,并在此先感谢您提供的任何输入或技巧。

Taking your last problem, first, incorrect syntax with "IN": 首先考虑最后一个问题,即“ IN”的不正确语法:

 case
 when T.status is null in t.date between '01-01-2017' and '01-31-2017'  
 and T.status = '1' in T.date between '02-01-2017' and '02-28-2017' then 'New Status to 1'
 else
 'test'
 end

Try: 尝试:

 case
 when (T.status is null AND t.date between '01-01-2017' and '01-31-2017')  
 OR (T.status = '1' AND T.date between '02-01-2017' and '02-28-2017') then 'New Status to 1'
 else
 'test'
 end

For easier checking the change in status, join your table to itself with a one-month offset. 为了更轻松地检查状态更改,请以一个月的补偿将表连接到自身。

I added an example table with input data in a WITH clause, which could match your requirement. 我在WITH子句中添加了带有输入数据的示例表,它可以满足您的要求。 I'm using the LAG() analytic function, which is supported by SQL Server. 我正在使用SQL Server支持的LAG()分析函数。 Remember that, in the first row in a partition of an analytic window, LAG() returns NULL - as there is no previous row in that case. 请记住,在分析窗口分区的第一行中,LAG()返回NULL-因为在这种情况下没有前一行。

In other DBMSs than SQL Server, you will need the ANSI concatenation operator || 在SQL Server以外的其他DBMS中,您将需要ANSI串联运算符|| instead of + to concatenate two strings. 而不是+来连接两个字符串。

WITH
input(input_id,monthfirst,status) AS (
          SELECT 1,DATE '2017-01-01',0
UNION ALL SELECT 1,DATE '2017-02-01',1
UNION ALL SELECT 1,DATE '2017-03-01',0
UNION ALL SELECT 2,DATE '2017-01-01',1
UNION ALL SELECT 2,DATE '2017-02-01',1
UNION ALL SELECT 2,DATE '2017-03-01',0
UNION ALL SELECT 3,DATE '2017-01-01',CAST(NULL AS INT)
UNION ALL SELECT 3,DATE '2017-02-01',1
UNION ALL SELECT 3,DATE '2017-03-01',0
)
,
input_with_prev_status AS (
SELECT
  *
, LAG(status) OVER (PARTITION BY input_id ORDER BY monthfirst) AS prev_status
FROM input
)
SELECT
  input_id
, monthfirst
, status
, CASE
    WHEN prev_status IS NULL AND status IS NOT NULL
      THEN 'New status to ' + CAST(status AS CHAR(1))
    WHEN prev_status <> status
      THEN 'Status changed to ' + CAST(status AS CHAR(1))
    WHEN prev_status = status
      THEN 'no status change'
    WHEN prev_status IS NULL AND status IS NULL
      THEN 'status remains missing'
    ELSE 'unforeseen status change'
  END AS status_change
FROM input_with_prev_status
;
input_id|monthfirst|status|status_change
       1|2017-01-01|     0|New status to 0
       1|2017-02-01|     1|Status changed to 1
       1|2017-03-01|     0|Status changed to 0
       2|2017-01-01|     1|New status to 1
       2|2017-02-01|     1|no status change
       2|2017-03-01|     0|Status changed to 0
       3|2017-01-01|-     |status remains missing
       3|2017-02-01|     1|New status to 1
       3|2017-03-01|     0|Status changed to 0

See code for self join (suggested by Dejan) below. 请参见下面的自我连接代码(由Dejan建议)。 You need to create the ON statement using the key column in table T 您需要使用表T中的键列创建ON语句

select 
  case 
  when (T1.[status] = '1' and T2. [status] = '1') or (T1.[status] = '0' and T2. [status] = '0') then 'No Change'
  when T1.[status] = '1' and T2. [status] = '0' then 'Status Changed to 0'
  when T1.[status] = '0' and T2. [status] = '1' then 'Status Changed to 1'
  when T.status is null and  T2. [status] = '1' then 'New Status to 1'
 else
 'test'
  end
table T1 
inner join T2
   on ....join on the key column
where T1.date between '01-01-2017' and '31-01-2017' 
and T2.date between '01-02-2017' and '28-02-2017'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM