MAX() 函数如何工作

问题描述 投票:0回答:2

我试图理解oracle中的MAX函数,我无法理解当列连接时它是如何工作的。

select max(effdate) from
(
select to_date('30-SEP-2023','DD-MON-YYYY') effdate from dual
union
select to_date('31-DEC-2022','DD-MON-YYYY') EFFDATE from dual
);

结果:符合预期

2023 年 9 月 30 日 00:00:00

查询2:

select max(effdate||' ==== '||amt) from
(
select to_date('30-SEP-2023','DD-MON-YYYY') effdate, 14 amt from dual
union
select to_date('31-DEC-2022','DD-MON-YYYY') EFFDATE, 10 amt from dual
);

结果:

2022 年 12 月 31 日 00:00:00 ==== 10

我预计:2023 年 9 月 30 日 ==== 14

问题3:

select max(effdate||' ==== '||amt) from
(
select to_date('30-SEP-2023','DD-MON-YYYY') effdate, 14 amt from dual
union
select to_date('30-DEC-2022','DD-MON-YYYY') EFFDATE, 10 amt from dual
);

结果:

2023 年 9 月 30 日 00:00:00 ==== 14

有人可以解释一下 MAX() 在这里是如何工作的吗?

database oracle max
2个回答
1
投票

将日期与字符串连接后,它会变成字符串,因此,最大值是按字母顺序导出的,而不是基于日期顺序:

这里如何根据日期然后通过 amt 获取最大值:

SELECT effdate || ' ==== ' || amt 
FROM (
  SELECT to_date('30-SEP-2023','DD-MON-YYYY') effdate, 14 amt FROM dual
  UNION
  SELECT to_date('31-DEC-2022','DD-MON-YYYY') EFFDATE, 10 amt FROM dual
)
ORDER BY effdate DESC, amt DESC
FETCH FIRST 1 ROWS ONLY

0
投票

查询 2 有效:

WITH sample_data (effdate, amt) AS (
  SELECT DATE '2023-09-30', 14 FROM DUAL UNION ALL
  SELECT DATE '2022-12-31', 10 FROM DUAL
)
SELECT MAX(
         TO_CHAR(
           effdate,
           (SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
         )
         || ' ==== '
         || TO_CHAR(amt)
       ) AS maximum
from   sample_data;

当您执行从

DATE
到字符串的隐式转换时,Oracle 将使用
TO_CHAR
会话参数的当前值作为日期的格式模型在日期上隐式调用
NLS_DATE_FORMAT

如果您使用:

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';

并运行查询,则输出为:

最大
2022 年 12 月 31 日 ==== 10

由于它将日期格式设置为

31-DEC-2022
30-SEP-2023
,并且在比较字符串时
'31'
大于
'30'
,因此它将采用最大字母值(而不是最大日期值)。

如果您使用:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

然后运行完全相同的查询,输出为:

最大
2023-09-30 00:00:00 ==== 14

隐式格式模型已更改,因此日期组成部分的顺序已更改,并且字符串中字符的字母数字排序顺序对应于日期的顺序,以便您获得预期的输出。

由此得出的结论是:

  1. 永远不要依赖隐式字符串转换;和
  2. 如果您想对数据进行排序,请不要将其转换(尤其是隐式)为不适当的数据类型。

从 Oracle 12 开始,您可以使用:

WITH sample_data (effdate, amt) AS (
  SELECT DATE '2023-09-30', 14 FROM DUAL UNION ALL
  SELECT DATE '2022-12-31', 10 FROM DUAL
)
SELECT *
from   sample_data
ORDER BY effdate DESC
FETCH FIRST ROW ONLY;

获取最大日期和对应的

amt

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.