SQL-запрос - игнорировать строку, если данные имеют значение NULL для нескольких строк при одном условии

У меня есть таблица ниже

Сид шаг cr_time 120 S02 08 июля 24 35.09.19.000 120 S03 08 июля 24 35.01.19.000 120 S04 09 июля 24 35.02.19.000 121 S02 09 июля 24 35.07.19.000 121 S03 09 июля 24 35.02.19.000 122 S02 10 июля 24, 35.10.19.000 122 S03 10 июля 24 35.05.19.000

Теперь мне нужно получить данные, только если время S02 и S03 находится между 8:30 и 16:30. Мне удалось добиться этого частично, но если какой-либо шаг не удовлетворяет условию, строка не должна быть получена. В моем случае она имеет значение null. Ниже приведен запрос

select 
    cid,
    min(case when step = 'S02' then cr_time end) S02_time,
    min(case when step = 'S03' then cr_time end) S03_time
from t where
    (CAST (cr_time as TIME) >= '8:30:00 AM' and CAST (cr_time as TIME) <= '4:30:00 PM')
group by cid;

Мне просто нужен ответ, как показано ниже, а не нулевые строки

Сид S02_cr_time S03_cr_time 120 24 июля 35.08.19.000 08 июля 24 35.01.19.000

Ссылка на тестер запросов: https://sqlize.online/sql/oracle23/22fd2bd79a6de38f592e7c225bde00a5/

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
0
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Попробуйте добавить предложение HAVING, как показано ниже:

select 
    cid,
    min(case when step = 'S02' then cr_time end) S02_time,
    min(case when step = 'S03' then cr_time end) S03_time
from t where
    (CAST (cr_time as TIME) >= '8:30:00 AM' and CAST (cr_time as TIME) <= '4:30:00 PM')
group by cid
HAVING S02_time IS NOT NULL AND S03_time IS NOT NULL;

Получение ошибки ORA-00904 - «S02_time»: неверный идентификатор @Sebastian

H Varma 22.07.2024 07:54

Похоже, вы выбрали «Oracle Database 21c» в качестве среды выполнения. Измените это на «Oracle Database 23c Free» и попробуйте.

Sebastian Srikanth Kumar 22.07.2024 08:06

Да, в моей рабочей среде выдает ту же ошибку. Почему это не работает в Oracle 21? Есть ли альтернативный подход?

H Varma 22.07.2024 08:07
sqize.online/sql/oracle23/737e4f4d8cff8fea4b988d8d54d5395b
Sebastian Srikanth Kumar 22.07.2024 08:07

Есть ли альтернативный подход?

H Varma 22.07.2024 08:08

Альтернативным подходом может быть использование CTE (Common Table Expression), как показано ниже: sql with cte as( select cid, min(case when step = 'S02' then cr_time end) S02_time, min(case when step = 'S03' then cr_time end) S03_time from t where (CAST (cr_time as TIME) >= '8:30:00 AM' and CAST (cr_time as TIME) <= '4:30:00 PM') group by cid ) select * from cte where S02_time IS NOT NULL AND S03_time IS NOT NULL ; sqize.online

Sebastian Srikanth Kumar 22.07.2024 08:24

Это работает. Есть ли способ получить разницу между этими двумя значениями времени в новом столбце?

H Varma 22.07.2024 08:34

Вы можете использовать HAVING для фильтрации после агрегирования и вычесть значения, чтобы найти разницу во времени:

SELECT cid,
       MIN(CASE WHEN step = 'S02' THEN cr_time END) S02_time,
       MIN(CASE WHEN step = 'S03' THEN cr_time END) S03_time,
       MIN(CASE WHEN step = 'S03' THEN cr_time END)
         - MIN(CASE WHEN step = 'S02' THEN cr_time END) AS diff
FROM   t
WHERE  CAST(cr_time AS TIME) BETWEEN TIME '08:30:00' AND TIME '16:30:00'
GROUP BY cid
HAVING MIN(CASE WHEN step = 'S02' THEN cr_time END) IS NOT NULL
AND    MIN(CASE WHEN step = 'S03' THEN cr_time END) IS NOT NULL;

Примечание. До версии Oracle 23 нельзя использовать псевдонимы, определенные в предложении SELECT в предложении HAVING.

Что для примера данных:

CREATE TABLE t (
  cid     INT,
  step    CHAR(3),
  cr_time TIMESTAMP
);

INSERT INTO t (cid, step, cr_time) 
SELECT 120, 'S02',  TIMESTAMP '2024-07-08 09:35:19.000' FROM DUAL UNION ALL
SELECT 120, 'S03',  TIMESTAMP '2024-07-08 13:35:19.000' FROM DUAL UNION ALL
SELECT 120, 'S04',  TIMESTAMP '2024-07-09 14:35:19.000' FROM DUAL UNION ALL
SELECT 121, 'S02',  TIMESTAMP '2024-07-09 07:35:19.000' FROM DUAL UNION ALL
SELECT 121, 'S03',  TIMESTAMP '2024-07-09 14:35:19.000' FROM DUAL UNION ALL
SELECT 122, 'S02',  TIMESTAMP '2024-07-10 10:35:19.000' FROM DUAL UNION ALL
SELECT 122, 'S03',  TIMESTAMP '2024-07-10 17:35:19.000' FROM DUAL;

Выходы:

CID S02_TIME S03_TIME РАЗНИЦА 120 2024-07-08 09:35:19.000000 2024-07-08 13:35:19.000000 +000000000 04:00:00.000000

рабочий пример

Другие вопросы по теме