0

这可能很简单,但我无法获得所需的输出。

我正在使用下面这个简单的查询来获取最新exp_dateitem_no

select g.item_no,max(g.exp_date)
from grn_drug_item g
group by g.item_no

第一个查询仅显示以下结果01-AUG-20

IT00002530 01-AUG-20

现在我想过滤“特定”最新的上述结果exp_date(例如:01-AUG-20如上所述),所以我将查询修改为:

select g.item_no,max(g.exp_date)
from grn_drug_item g
where g.exp_date = to_date('01-AUG-20','DD-MON-YY')
group by g.item_no

但这给了我多行,如果我使用where g.item_no = 'IT00002530'它会获取所需的输出。

我怎样才能让过滤器在此处为特定对象工作exp_date

4

6 回答 6

3

如果无法访问您的数据,这有点推测,但看起来您正在挑选具有较晚exp_date. 您的过滤器太早了 - 那些日期较晚特定日期的项目将包含在过滤器中,并且该子集中的最大日期显然是同一日期。

您可以在分组后应用过滤器having

select g.item_no,max(g.exp_date)
from grn_drug_item g
group by g.item_no
having max(g.exp_date) = to_date('01-AUG-20','DD-MON-YY')

'YY' 的使用有点令人担忧;使用两位数年份是个问题,但如果必须,请使用RR. 不过最好使用 4 位数年份,对于固定日期,使用日期文字更简单:

having max(g.exp_date) = date '2020-08-01'
于 2020-08-14T09:15:15.820 回答
2

这是因为您使用了该WHERE子句。您的查询当前选择在 8 月 1 日有一个到期实例但可以有多个到期日期的所有项目。

使用HAVING MAX(g.exp_date) = to_date('01-AUG-20','DD-MON-YY')应该可以得到你想要的,因为它标识了每个项目的最新到期日期。您的查询应如下所示:

select g.item_no, max(g.exp_date)
from grn_drug_item g
group by g.item_no
having max(g.exp_date) = to_date('01-AUG-20','DD-MON-YY')
于 2020-08-14T09:17:50.843 回答
2

这与其他答案略有不同。但是您可能会发现在聚合之前进行过滤可以显着提高性能:

select g.item_no, max(g.exp_date)
from grn_drug_item g
where g.exp_date >= date '2020-08-01'
group by g.item_no
having max(g.exp_date) = date '2020-08-01';

这可以显着减少需要聚合的数据量。还要注意使用date来引入日期常量。

于 2020-08-14T10:59:21.153 回答
2

TL;DR - 使用子句分组后过滤日期HAVING,您可能还需要过滤 24 小时范围而不是单个日期(如果您的日期具有用户未显示的非午夜时间部分 -您正在使用的界面)。


让我们假设您有如下示例数据:

CREATE TABLE grn_drug_item ( item_no, exp_date ) AS
SELECT 'IT00002530', DATE '2020-08-01' + INTERVAL '12:00:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT 'IT00002530', DATE '2020-07-01' FROM DUAL UNION ALL
SELECT 'ANOTHER001', DATE '2020-08-01' FROM DUAL UNION ALL
SELECT 'ANOTHER001', DATE '2020-08-05' FROM DUAL UNION ALL
SELECT 'OTHER00002', DATE '2020-07-01' FROM DUAL UNION ALL
SELECT 'OTHER00002', DATE '2020-08-04' FROM DUAL;

并且您的NLS_DATE_FORMAT会话参数设置为 America/China/UK的默认值DD-MON-RR

然后,如果您使用查询:

SELECT g.item_no,
       MAX(g.exp_date)
FROM   grn_drug_item g
GROUP BY g.item_no

你会得到输出:

项目_NO | MAX(G.EXP_DATE)
:--------- | :--------------
另一个001 | 20 年 8 月 5 日      
其他00002 | 20 年 8 月 4 日      
IT00002530 | 20 年 8 月 1 日      

这符合您的以下陈述:

第一次查询仅显示 01-AUG-20 的以下结果

 IT00002530 01-AUG-20

如果我们运行查询:

SELECT g.item_no,
       MAX(g.exp_date)
FROM   grn_drug_item g
WHERE  g.exp_date = DATE '2020-08-01'
GROUP BY g.item_no

然后我们在分组前过滤行,并从过滤后的行中获得最大值;输出:

项目_NO | MAX(G.EXP_DATE)    
:--------- | :-----------------
另一个001 | 2020-08-01T00:00:00

NLS_DATE_FORMAT现在设置为 ISO8601 格式YYYY-MM-DD"T"HH24:MI:SS以显示时间分量)

这仅显示具有恰好ITEM_NO所在行的行。由于样本数据具有时间分量,因此未显示在结果中。EXP_DATE2020-08-01T00:00:00IT0000253012:00:00

要复制您的结果,我需要在 24 小时内过滤,而不是在午夜过滤一个实例:

SELECT g.item_no,max(g.exp_date)
FROM   grn_drug_item g
WHERE  g.exp_date >= DATE '2020-08-01'
AND    g.exp_date <  DATE '2020-08-01' + INTERVAL '1' DAY
GROUP BY g.item_no

这将输出:

项目_NO | MAX(G.EXP_DATE)    
:--------- | :-----------------
另一个001 | 2020-08-01T00:00:00
IT00002530 | 2020-08-01T12:00:00

但是您似乎想要当天最大值所在的行,01-AUG-20因此您需要计算最大值然后对其进行过滤;您可以使用HAVING子句而不是WHERE子句来做到这一点:

SELECT g.item_no,
       MAX(g.exp_date)
FROM   grn_drug_item g
GROUP BY g.item_no
HAVING MAX(g.exp_date) >= DATE '2020-08-01'
AND    MAX(g.exp_date) <  DATE '2020-08-01' + INTERVAL '1' DAY;

(同样,如果您的日期的时间部分并不总是设置为午夜,那么您希望过滤 24 小时范围而不是单个瞬间。)

哪个输出:

项目_NO | MAX(G.EXP_DATE)    
:--------- | :-----------------
IT00002530 | 2020-08-01T12:00:00

db<>在这里摆弄

于 2020-08-14T13:09:01.137 回答
1

where 子句在 GROUP BY 之前执行,因此您不会获得最高 exp_date = 1/8/2020 的项目,但您会获得至少一个 exp_date = 1/8/2020 的项目。

要在分组后对结果应用过滤,您需要使用 HAVING:

select g.item_no,max(g.exp_date) as max_exp_date
from grn_drug_item g
group by g.item_no
having max_exp_date = to_date('01-AUG-20','DD-MON-YY')
于 2020-08-14T09:16:42.417 回答
1

要添加到@AlexPoole 的答案,您可能还需要考虑将您的简单脚本转换为存储过程

这将允许您在通话中使用可变日期。例如:

CREATE PROCEDURE getItemNumbersByMaxDate
    @maxDate AS DATE --  Assuming SQL can utilise DATE type
AS
    SELECT   g.item_no,max(g.exp_date)
    FROM     grn_drug_item g
    GROUP BY g.item_no
    HAVING   MAX(g.exp_date) >= @maxDate

请注意,我是为 T-SQL 编写的,您可能需要针对 Oracle 进行调整。

于 2020-08-14T09:27:12.780 回答