CASE .. WHEN вираз в Oracle SQL


79

У мене є таблиця з 1 стовпцем і є наступні дані

Status
a1
i
t
a2
a3

Я хочу відобразити такий результат у своєму запиті на вибір

Status| STATUSTEXT
a1    | Active
i     | Inactive
t     | Terminated
a2    | Active
a3    | Active

Я міг подумати, що використовую вираз Switch When у запиті select

SELECT
status,
CASE status 
WHEN 'a1' THEN 'Active'
WHEN 'a2' THEN 'Active'
WHEN 'a3' THEN 'Active'
WHEN 'i' THEN 'Inactive'
WHEN 't' THEN 'Terminated'
END AS StatusText
FROM stage.tst

Чи є інший спосіб зробити це, коли мені не потрібно писати, коли вираз 3 рази для активного стану і весь активний статус можна перевірити в одному вираз?

Відповіді:


133

Ви можете використати INречення

Щось на зразок

SELECT
  status,
  CASE
    WHEN STATUS IN('a1','a2','a3')
    THEN 'Active'
    WHEN STATUS = 'i'
    THEN 'Inactive'
    WHEN STATUS = 't'
    THEN 'Terminated'
  END AS STATUSTEXT
FROM
  STATUS

Погляньте на цю демонстрацію

SQL-скрипка DEMO


2
Якщо можу, я пропоную явно додати ІНШЕ "НЕВІДОМЕ - БУДЬ ЛАСКА, ЗАтелефонуй нам" або інший такий прапор. У більших системах обробки даних із великою кількістю користувачів іноді нові значення потрапляють у дані, і може бути корисно закликати користувачів помітити вас і зв’язатися з вами. Я вважаю, що без цього поле "STATUSTEXT" буде просто порожнім, що генерує менше коментарів користувачів. +1 Адріанові за приємний відступ теж.
noogrub

Хороший момент від noogrub. Я хотів би додати ELSE statusраніше, ENDтак що якщо новий статус все-таки закрадеться, ви отримаєте базове значення стану, а не нуль для STATUSTEXT. Я б не став за замовчуванням, ELSE 'active'якщо інші неактивні або припинені статуси вводяться іншими. За замовчуванням значення "активний" вимагає неприємностей.
Джефф Мерглер,

18

Звичайно...

select case substr(status,1,1) -- you're only interested in the first character.
            when 'a' then 'Active'
            when 'i' then 'Inactive'
            when 't' then 'Terminated'
       end as statustext
  from stage.tst

Однак у цій схемі є кілька тривожних речей. По-перше, якщо у вас є стовпець, який щось означає, додавання числа в кінець - це не обов’язково найкращий шлях. Крім того, залежно від кількості статусу, який у вас є, ви можете розглянути можливість перетворення цього стовпця на зовнішній ключ до окремої таблиці.


Виходячи з вашого коментаря, ви точно хочете перетворити це на зовнішній ключ. Наприклад

create table statuses ( -- Not a good table name :-)
    status varchar2(10)
  , description varchar2(10)
  , constraint pk_statuses primary key (status)
    )

create table tst (
    id number
  , status varchar2(10)
  , constraint pk_tst primary key (id)
  , constraint fk_tst foreign key (status) references statuses (status)
    )

Тоді ваш запит стає

select a.status, b.description
  from tst a
  left outer join statuses b
    on a.status = b.status

Ось скрипт SQL для демонстрації.


Я навів загальний приклад своєї справи. Однак мене цікавить не лише перший персонаж.
Nilesh Barai

+1, особливо за згадку про тривожні речі щодо цієї схеми.
Роб ван Війк,

17

Ви можете переписати його, щоб використовувати умову ELSE CASE:

SELECT status,
       CASE status
         WHEN 'i' THEN 'Inactive'
         WHEN 't' THEN 'Terminated'
         ELSE 'Active'
       END AS StatusText
FROM   stage.tst 

6

Це буде простіше зробити за допомогою декодування .

SELECT
  status,
    decode ( status, 'a1','Active',
                     'a2','Active',
                     'a3','Active',
                     'i','Inactive',
                     't','Terminated',
                     'Default')STATUSTEXT
FROM STATUS

2

Оскільки веб-пошук для Oracle caseвершин цього посилання, я додаю тут для виписки справи , хоча і не відповідаю на запитання про вираз справи :

CASE
   WHEN grade = 'A' THEN dbms_output.put_line('Excellent');
   WHEN grade = 'B' THEN dbms_output.put_line('Very Good');
   WHEN grade = 'C' THEN dbms_output.put_line('Good');
   WHEN grade = 'D' THEN dbms_output.put_line('Fair');
   WHEN grade = 'F' THEN dbms_output.put_line('Poor');
   ELSE dbms_output.put_line('No such grade');
END CASE;

або інший варіант:

CASE grade
   WHEN 'A' THEN dbms_output.put_line('Excellent');
   WHEN 'B' THEN dbms_output.put_line('Very Good');
   WHEN 'C' THEN dbms_output.put_line('Good');
   WHEN 'D' THEN dbms_output.put_line('Fair');
   WHEN 'F' THEN dbms_output.put_line('Poor');
   ELSE dbms_output.put_line('No such grade');
END CASE;

За документами Oracle: https://docs.oracle.com/cd/B10501_01/appdev.920/a96624/04_struc.htm


здається, не підтримується написання кратних у whenдругому варіанті, наприклад case grade when 1,2 then. якщо ви знаєте інакше, будь ласка, коментуйте.
Олексій

1
SELECT
  STATUS,
  CASE
    WHEN STATUS IN('a1','a2','a3') 
     THEN 'Active'
    WHEN STATUS = 'i' 
     THEN 'Inactive'
    WHEN STATUS = 't'
     THEN 'Terminated'  ELSE null
  END AS STATUSTEXT
FROM
  stage.tst;

1
Хоча цей фрагмент коду вітається і може надати певну допомогу, його було б значно покращено, якби він містив пояснення того, як він вирішує питання. Без цього ваша відповідь має набагато меншу освітню цінність - пам’ятайте, що ви відповідаєте на запитання читачам у майбутньому, а не лише тому, хто запитує зараз! Будь ласка, відредагуйте свою відповідь, щоб додати пояснення, та вкажіть, які обмеження та припущення застосовуються
Жан,

0

Ви можете перевірити лише перший символ стану. Для цього ви використовуєте функцію підрядка.

substr (статус, 1,1)

У вашому випадку минуле.


0

Працював би наступний синтаксис:

....
where x.p_NBR =to_number(substr(y.k_str,11,5))
and x.q_nbr = 
 (case 
 when instr(substr(y.m_str,11,9),'_') = 6   then  to_number(substr(y.m_str,11,5))
 when instr(substr(y.m_str,11,9),'_') = 0   then  to_number(substr(y.m_str,11,9))
  else 
       1
  end
)

0
CASE TO_CHAR(META.RHCONTRATOSFOLHA.CONTRATO)
WHEN '91' AND TO_CHAR(META.RHCONTRATOSFOLHA.UNIDADE) = '0001' THEN '91RJ'
WHEN '91' AND TO_CHAR(META.RHCONTRATOSFOLHA.UNIDADE) = '0002' THEN '91SP'
END CONTRATO,

00905. 00000 -  "missing keyword"
*Cause:    
*Action:
Erro na linha: 15 Coluna: 11

2
Поясніть, будь ласка, як це відповідає на 8-річне питання.
Dragonthoughts
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.