WHERE子句中的IF语句 - SQL - Oracle

时间:2017-08-09 04:24:41

标签: sql oracle

我的表格结构如下:

ID     STATUS_1   STATUS_2   VERSION
1      Success    Disabled      5
2      Disabled   In_Progress   3
3      Disabled   Disabled      4

我需要返回所有行

  • STATUS_1或STATUS_2可以是SuccessIn_Progress
  • 如果没有行具有SuccessIn_Progress状态的STATUS_1或STATUS_2,则应返回具有最低VERSION值的行。

在当前表中,返回的行将是:

1      Success    Disabled      5
2      Disabled   In_Progress   3

所以如果我的表看起来像这样:

ID     STATUS_1   STATUS_2   VERSION
1       --        Disabled     5
2       Disabled  --           3
3       Disabled  Disabled     4

返回的唯一行应为

2       Disabled  --           3

因为它的版本最低(3)。

这可以通过IF子句中的WHERE语句完成吗?

4 个答案:

答案 0 :(得分:1)

以下查询似乎是您想要的。首先,我使用CTE计算具有SuccessIn_progress的记录数。稍后,我们可以使用此计数来确定是否需要返回具有最低版本的单行,或者所有匹配的行。

我在查找找到最低版本记录的查询和返回所有匹配行的第二个查询之间取UNION。诀窍是,UNION的前半部分中的单行仅在匹配计数为零时才会保留。否则,它将被删除,UNION的这部分将不对结果集做出任何贡献。请注意,如果我们确实保留了单个最低版本的记录,那么根据定义,查询的后半部分本身不会返回任何内容,仍然会在结果集中留下我们的单个记录。

WITH cte AS (
    SELECT COUNT(*) cnt
    FROM yourTable
    WHERE
        STATUS_1 IN ('Success', 'In_Progress') OR
        STATUS_2 IN ('Success', 'In_Progress')
)

SELECT t.ID, t.STATUS_1, t.STATUS_2, t.VERSION
FROM
(
    SELECT ID, STATUS_1, STATUS_2, VERSION,
        ROW_NUMBER() OVER (ORDER BY VERSION) rn
    FROM yourTable
) t
WHERE
    t.rn = 1 AND
    (SELECT cnt FROM cte) = 0

UNION ALL

SELECT ID, STATUS_1, STATUS_2, VERSION
FROM yourTable
WHERE
    STATUS_1 IN ('Success', 'In_Progress') OR
    STATUS_2 IN ('Success', 'In_Progress')

以下是一个演示,您可以在其中探索此查询:

Rextester

请注意,我在演示中使用了SQL Server,因为设置Oracle演示很麻烦,但是查询应该在很少或没有修改的情况下在Oracle上运行。

答案 1 :(得分:0)

您可以使用CASE语句,它的作用类似于IF-THEN-ELSE

答案 2 :(得分:0)

请尝试以下查询,并告诉我它是否有效

    select id,STATUS_1,status_2,version from status 
        where status_1 in ('In progress','Success') 
        and Status_2 in ('In progress','Success')
    union all
    select id,status_1,status_2,version from 
      (
             select id,status_1,status_2,version,
             row_number() over(order by version) as rn 
             from status 
             where status_1 not in ('In progress','Success') or 
                   status_2 not in ('In progress','Success')
      )a
    where a.rn=1 

答案 3 :(得分:0)

对于if else,你可以使用“case when ......”,“coalesce()”或“decode()”。以下示例使用“case when ......”。

create table states (
   ID       number, 
   STATUS_1 varchar2(50),   
   STATUS_2 varchar2(50),   
   VERSION  number
);

insert into states values (1,      'Success',    'Disabled',      5);
insert into states values (2,      'Disabled',   'In_Progress',   3);
insert into states values (3,      'Disabled',   'Disabled',      4);

select t.* 
  from ( select s.*, 
                rank() over (order by version asc) as rnk,
                count( case 
                          when s.status_1 = 'Success' then 1 
                          when s.status_1 = 'In_Progress' then 1
                          when s.status_2 = 'Success' then 1 
                          when s.status_2 = 'In_Progress' then 1 
                          else null
                        end
                     ) over () as cnt
           from states s ) t
  where (t.rnk = 1 and t.cnt = 0)
     or (t.status_1 in ('Success',    'In_Progress'))
     or (t.status_2 in ('Success',    'In_Progress'))

玩得开心