Запрос в Oracle для выбора с помощью подзапроса - PullRequest
3 голосов
/ 29 февраля 2020

В моей базе данных Oracle есть следующая таблица:

CREATE TABLE test
(
 flight NUMBER(4),
 date   DATE,
 action VARCHAR2(50),
 CONSTRAINT pk PRIMARY KEY (flight,date)
);

и следующие регистры:

BEGIN
 INSERT INTO test VALUES ('1234', '2020-02-29 18:00', 'Departure');
 INSERT INTO test VALUES ('1234', '2020-02-29 19:00', 'Arrival');

 INSERT INTO test VALUES ('4321', '2020-02-20 22:00', 'Departure');
 INSERT INTO test VALUES ('4321', '2020-02-21 04:30', 'Arrival');
END;
/

Моя проблема в том, что я хочу сделать SELECT, который возвращает мне номер рейса только тогда, когда он вылетел и прибыл в тот же день. Например, рейс «1234» вылетел в день 29 и прибыл в день 29, но, с другой стороны, рейс «4321» вылетел на день 20 и прибыл в день 21. Я только хотел бы выбрать рейс «1234». ', потому что это единственный, кто отвечает требованиям.

Я думал о следующем выборе, но он не работает, потому что подзапрос возвращает более одного значения:

SELECT flight
  FROM test
 WHERE action = 'Departure'
   AND TO_CHAR(date, 'YYYY-MM-DD') = (SELECT TO_CHAR(date, 'YYYY-MM-DD')
                                        FROM test
                                       WHERE action = 'Arrival');

Большое спасибо.

Ответы [ 6 ]

1 голос
/ 29 февраля 2020

Мы не знаем, представляет ли номер рейса в вашей модели данных уникальный рейс или нет. Мы также не знаем, возможны ли какие-либо действия помимо «Вылет» и «Прибытие».

Следующие решения рассматривают номер рейса в сочетании с датой рейса и рассматривают два рассматриваемых действия, поэтому они работают в любом случае:

С INTERSECT:

select flight, trunc(date) from test where action = 'Departure'
intersect
select flight, trunc(date) from test where action = 'Arrival';

С агрегацией:

select flight, trunc(date)
from test
group by flight, trunc(date)
having count(case when action = 'Departure' then 1 end) = 1
   and count(case when action = 'Arrival' then 1 end) = 1;
1 голос
/ 29 февраля 2020

Тебе просто нужны конкретные действия в течение дня. Таким образом, используйте количество HAVING для двух отдельных действий GROUPed BY рейс и день:

SELECT flight
  FROM test
 WHERE action in ('Departure','Arrival')
 GROUP BY flight, trunc("date")
HAVING COUNT(distinct action)=2

, где должно быть предложение distinct, необходимость наблюдается, если расширен набор данных образца

Демо

  • date является зарезервированным ключевым словом и не может использоваться в качестве имени столбца для базы данных Oracle. Итак, я предпочел "date"
  • Префикс литералов времени с ключевым словом timestamp и добавление части :00 в конце для представления second, например timestamp'2020-02-21 04:30:00' во время вставки
0 голосов
/ 01 марта 2020

Оператор PIVOT тоже может работать

SELECT *
FROM (SELECT flight, date, action
    FROM test)

PIVOT
    (
      MAX(DATE)
      FOR ACTION IN ('Departure' AS DEP, 'Arrival' AS AR)
    )WHERE TRUNC(DEP) = TRUNC(AR)
0 голосов
/ 29 февраля 2020

Еще одним вариантом является использование join с номером рейса и датой следующим образом:

SELECT distinct d.flight
  FROM test d JOIN test a 
    ON d.action = 'Departure'
    AND trunc(d.date) = trunc(a.date)
    AND a.action = 'Arrival'
    AND a.flight = d.flight;

Cheers !!

0 голосов
/ 29 февраля 2020

С COUNT() оконной функцией:

select distinct flight
from (
  select t.*, 
    count(distinct action) over (partition by flight, to_char("date", 'YYYY-MM-DD')) counter
  from test t
)
where counter = 2

См. Демоверсию . Результаты:

> | FLIGHT |
> | -----: |
> |   1234 |
0 голосов
/ 29 февраля 2020

Вам требуется одна и та же таблица два раза в соединении

SELECT t1.flight
FROM test t1
INNER JOIN test t2 ON t1.action = 'Departure'
    AND TO_CHAR(t1.date, 'YYYY-MM-DD')  = TO_CHAR(t2.date, 'YYYY-MM-DD')
    AND t2.action = 'Arrival'
    AND t1.flight =t2.flight

Или используя подзапрос .. снова введите правильное предложение FROM

SELECT flight
FROM test
WHERE action = 'Departure'
AND (TO_CHAR(date, 'YYYY-MM-DD'), flight)  = (
    SELECT TO_CHAR(date, 'YYYY-MM-DD'), flight
    FROM test
    WHERE action = 'Arrival');        
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...