简体   繁体   English

在 Oracle 中查询以使用子查询进行选择

[英]Query in Oracle to select with subquery

I have the following table on my Oracle database:我的 Oracle 数据库中有下表:

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

and the following registers:以及以下寄存器:

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;
/

My problem is that I want to make a SELECT that returns me the flight number only when it has departed and arrived at the same day.我的问题是我想做一个 SELECT ,只有当它离开并在同一天到达时才返回我的航班号。 For example, flight '1234' has departed on day 29 and arrived on day 29, but in the other hand, the flight '4321' has departed on day 20 and arrived on day 21. I only would like to select the flight '1234', because it is the only one who meets the requeriments.例如,“1234”航班第 29 天起飞,第 29 天到达,而“4321”航班第 20 天起飞,第 21 天到达。我只想选择“1234”航班',因为它是唯一满足要求的。

I have been thinking about the following select, but it doesn't work because the subquery returns more than just one value:我一直在考虑以下选择,但它不起作用,因为子查询返回的值不止一个:

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');

Thank you so much.非常感谢。

You just need distinct action within a day.您只需要在一天内采取不同的行动。 So, use HAVING count distinctly of two individual actions GROUPed BY flight and day :因此,使用 HAVING 对按航班和天分组的两个单独操作进行明显计数:

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

where there should be distinct clause, need is observed if the sample data set is extended在应该有distinct条款的地方,如果扩展样本数据集,则需要观察

Demo 演示

  • date is a reserved keyword and cannot be used as a column name for Oracle database. date是保留关键字,不能用作 Oracle 数据库的列名。 So, I preferred "date"所以,我更喜欢"date"
  • Prefix the time literals with timestamp keyword and add portion :00 at the end to represent second such as timestamp'2020-02-21 04:30:00' during the insertiontimestamp关键字作为时间文字的前缀,并在最后添加部分:00来表示second例如在插入过程中timestamp'2020-02-21 04:30:00'

We don't know, whether a flight number in your data model uniquely represents a flight or not.我们不知道您的数据模型中的航班号是否唯一代表一次航班。 We also don't know whether there can be any actions apart from 'Departure' and 'Arrival'.我们也不知道除了“出发”和“到达”之外是否还有其他动作。

The following solutions look at a flight number in combination with the flight date and consider the two actions in question, so they work in any case:以下解决方案将航班号与航班日期结合起来考虑,并考虑相关的两个操作,因此它们在任何情况下都有效:

With INTERSECT :INTERSECT

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

With aggregation:使用聚合:

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;

You need the same table two time in join您需要两次加入同一张桌子

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

Or using the subquery ..use a proper FROM clause again或者使用子查询..再次使用正确的 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');        

With COUNT() window function:使用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

See the demo .请参阅演示
Results:结果:

> | FLIGHT |
> | -----: |
> |   1234 |

Yet another option is to use the join with flight number and date as follows:然而,另一种选择是使用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!!干杯!!

A PIVOT statement could work too 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)

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

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