在 Oracle 中取最大相关值?
Posted
技术标签:
【中文标题】在 Oracle 中取最大相关值?【英文标题】:Take max correlated value in Oracle? 【发布时间】:2020-07-16 16:24:08 【问题描述】:我的 Oracle 11g 数据库中有以下表:
CREATE TABLE travels
(
Day DATE,
Flight_Code VARCHAR2(7),
Airplane_Code VARCHAR2(7),
CONSTRAINT pk PRIMARY KEY(day,flight_code)
);
和
CREATE TABLE boardings
(
Passport VARCHAR2(7),
Day DATE,
Flight_Code VARCHAR2(7),
Luggage_Weight NUMBER(4,2),
CONSTRAINT pk PRIMARY KEY(passport,day,flight_code)
);
所以我试图进行查询,以查看每架飞机的最大重量(Day 和 Flight_Code),该重量始终高于 100(请记住同一个航班,例如 RY-1234-VY,可以在不同的日子进行不同的旅行,但同一天不能超过一次)。
我一直在尝试这样的事情,但它不起作用,因为它返回每个航班,这是它已经运输更多 Luggage_Weight 的那一天,以及完成它的飞机。
SELECT Airplane_Code, Day, Flight_Code
FROM Travels
WHERE (Day, Flight_Code) IN (SELECT Day, Flight_Code
FROM boardings b1
GROUP BY Day, Flight_Code
HAVING SUM(Luggage_Weight) = (SELECT MAX(SUM(Luggage_Weight))
FROM boardings b2
WHERE b1.Flight_Code = b2.Flight_Code
GROUP BY Day, Flight_Code
HAVING SUM(Luggage_Weight) > 100))
GROUP BY Airplane_Code, Day, Flight_Code;
我想要使用 GROUP BY 和 HAVING 结构的解决方案。
例如:
INSERT INTO travels VALUES ('04/04/2020', 'RY1234', 'ABCD');
INSERT INTO travels VALUES ('03/04/2020', 'RY1234', 'ABCD');
INSERT INTO boardings VALUES ('ES1234', '04/04/2020', 'RY1234', '51');
INSERT INTO boardings VALUES ('ES5678', '04/04/2020', 'RY1234', '50');
INSERT INTO boardings VALUES ('ES9101', '03/04/2020', 'RY1234', '100');
如您所见,同一个航班 (RY1234) 已在 2 个不同的日子旅行,因此在 03/04 总行李重量为 100 公斤,但在 04/04 总行李重量为 101 公斤。结果应该是下一个:
ABCD ---- 04/04/2020 ---- RY1234
如果同一架飞机的任何一次航班的重量都没有达到 100 公斤,则不应显示该飞机代码。
【问题讨论】:
Edit 问题并将示例数据添加为INSERT INTO
语句,并将所需结果添加为表格文本。
成功了!请看一下
【参考方案1】:
您可以在派生表中使用dense_rank()
,按照航班的权重sum()
对航班进行排名。然后将其加入travels
并过滤排名为1
。
SELECT t.airplane_code,
t.day,
t.flight_code
FROM travels t
INNER JOIN (SELECT b.day,
b.flight_code,
dense_rank() OVER (ORDER BY sum(b.luggage_weight) DESC) dr
FROM boardings b
GROUP BY b.day,
b.flight_code) x
ON x.day = t.day
AND x.flight_code = t.flight_code
WHERE x.dr = 1;
db<>fiddle
【讨论】:
您能告诉我如何使用 GROUP BY 和 HAVING 吗?只是更新我的尝试并告诉我要改变什么 @Trick:查询中有GROUP BY
,不是吗?
是的,我知道,但是如何只使用 GROUP BY 和 HAVING?我的意思是,不使用dense_rank()、OVER、ORDER BY...等想法。
但我需要像我说的那样
@Trick:没有限制,Oracle 可以做窗口函数。 11g也是。小提琴只有 18c,因为目前没有 11g。试试看吧。【参考方案2】:
select Airplane_Code,day,Flight_Code from (
Select Airplane_Code,day,Flight_Code ,sum(Luggage_Weight) over (Partition by
Flight_Code,day) as total_weight
from travels t,boardings b
where t.Flight_Code=b.Flight_Code)data1
where data1.total_weight >100;
【讨论】:
如果使用代码格式会更容易查看。另外,我说我更喜欢它是 GROUP BY 和 HAVING 结构【参考方案3】:您可以将子查询重构与 GROUP BY 和 HAVING 一起使用,如下所示。
当您说以下内容时,您需要单独按 Flight_code 分组以获得最大重量。
所以我试图进行查询,以便查看每架飞机的航班(Day 和 Flight_Code),它已经运输了最大重量,该重量始终高于 100(保持请记住,同一个航班,例如 RY-1234-VY,可以在不同的日子进行不同的旅行,但同一天不能超过一次)。
WITH t
AS (SELECT t.airplane_code,
t.day,
t.flight_code,
SUM(luggage_weight) wt
FROM travels t,
boardings b
WHERE t.flight_code = b.flight_code
AND Trunc(t.day) = Trunc(b.day)
GROUP BY t.airplane_code,
t.day,
t.flight_code
HAVING SUM(luggage_weight) > 100),
t1
AS (SELECT Max(wt) wt,
flight_code
FROM t
GROUP BY
flight_code)
SELECT t.*
FROM t,
t1
WHERE t.wt = t1.wt
AND t.flight_code = t1.flight_code
没有子查询重构,你可以像下面这样使用
SELECT t.airplane_code,
t.day,
t.flight_code
FROM travels t,
boardings b
WHERE t.flight_code = b.flight_code
AND Trunc(t.day) = Trunc(b.day)
GROUP BY t.airplane_code,
t.day,
t.flight_code
HAVING SUM(luggage_weight) IN (SELECT Max(wt) wt
FROM (SELECT b.day,
b.flight_code,
SUM(luggage_weight) wt
FROM boardings b
GROUP BY b.day,
b.flight_code
HAVING SUM(luggage_weight) > 100)rec
WHERE rec.flight_code = t.flight_code
GROUP BY t.flight_code)
你也可以使用类似下面的东西
SELECT *
FROM travels t
WHERE ( Trunc(t.day), t.flight_code ) IN (SELECT Trunc(b.day),
b.flight_code
FROM boardings b
GROUP BY b.day,
b.flight_code
HAVING SUM(luggage_weight) IN
(SELECT Max(wt) wt
FROM
(SELECT b.day,
b.flight_code,
SUM(luggage_weight)
wt
FROM boardings b
GROUP BY b.day,
b.flight_code
HAVING SUM(luggage_weight) >
100)rec
WHERE
rec.flight_code = b.flight_code
【讨论】:
不使用 WITH 会怎么样?我的意思是,结构与我展示的示例相似 更新了答案 这种情况下TRUNC的作用是什么? 如果 day 有时间值,则需要 trunc 但我不想显示行李重量的总和,只显示飞机代码、航班代码和日期。是否也需要加入登机牌?以上是关于在 Oracle 中取最大相关值?的主要内容,如果未能解决你的问题,请参考以下文章