第144章 SQL函数 TO_DATE(二)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第144章 SQL函数 TO_DATE(二)相关的知识,希望对你有一定的参考价值。
参考技术A 可以使用 DDD 将一年中的某一天(自 1 月 1 日以来经过的天数)转换为实际日期。格式字符串 DDD YYYY 必须与由整数天数和四位数年份组成的相应 date_string 配对。 (与 DDD 一起使用时,两位数的年份必须指定为 RR (而不是 YY )。)格式字符串 DDD 默认为当前年份。经过的天数必须是 1 到 365 范围内的正整数(如果 YYYY 是闰年,则为 366 )。四位数年份必须在标准 日期范围内: 1841 到 9999 。 DDD 和 YYYY 格式元素可以按任意顺序指定;它们之间的分隔符是强制性的。以下示例显示了这一年中的一天的用法:如果格式字符串同时包含 DD 和 DDD 元素,则 DDD 元素占主导地位。这在以下示例中显示,该示例返回 2/29/2020 (不是 12/31/2020 ):
TO_DATE 允许返回对应于一年中某一天的日期表达式。 TO_CHAR 允许返回与日期表达式对应的一年中的哪一天。
SQL中,儒略日可用于1840年12月31日之前的任何日期。因为在内部将这个日期表示为 0 ,所以需要特殊的语法来表示更早的日期。为此, TO_DATE 提供了 “J” (或 “J” )格式。儒略日转换将七位数的内部数值(儒略日计数)转换为显示格式或ODBC格式的日期。例如:
返回以下日期: 1585–01–31 (ODBC格式)或 01/31/1585 (显示格式)。儒略日计数 1721424 返回公元1年的1月1日( 1–01–01 )。儒略日计数,如 1709980 (亚克兴战役标志着罗马帝国在奥古斯都·凯撒统治下的开始)返回公元前(BC)日期,显示的年份前面有一个负号。
儒略日计数在内部总是表示为一个七位数,必要时带有前导零。 TO_DATE 允许输入不带前导零的儒略日计数。最大允许儒略日是 5373484 ,它返回 12/31/9999 。允许的最小儒略日是 0000001 ,它返回 01/01/-4712 (即BCE日期 01/01/-4713 )。任何超出此范围的值都会生成 SQLCODE -400 错误,其 %msg 值为“无效的儒略日值”。儒略日必须介于 1 和 5373484 之间。
注意:以下注意事项不应影响使用 TO_CHAR 和 TO_DATE 的日期和儒略日计数的相互转换。这可能会影响使用儒略日计数进行的一些计算。
1721424 (1/1/1) 之前的儒略日计数与其他软件实现兼容,例如 Oracle。它们与通常使用的 BCE 日期不同。正常使用中,没有 Year 0 ;日期从 12/31/-1 到 1/1/1 。在 Oracle 使用中,儒略日期 1721058 到 1721423 完全无效,并返回错误。这些儒略日期返回不存在的第 0 年作为占位符。因此,涉及 BCE 日期的计算必须调整一年以对应于常见用法。
另请注意,这些日期计数并未考虑公历改革(1582 年 10 月 15 日颁布,但直到 1752 年才在英国及其殖民地采用)引起的日期变化。
TO_DATE 允许返回对应于儒略日计数的日期表达式。 TO_CHAR 允许返回对应于日期表达式的儒略日计数,如以下示例所示:
以下嵌入式 SQL 示例指定使用默认日期格式解析的日期字符串。这两个都转换为 DATE 数据类型内部值 60537 :
以下嵌入式 SQL 示例指定具有两位数年份的日期字符串,格式为默认值。请注意,两位数年份默认为 1900 到 1999 。因此,内部 DATE 值为 24012 :
以下嵌入式 SQL 示例以各种格式指定日期字符串。所有这些都转换为 DATE 数据类型内部值 64701 。
以下嵌入式 SQL 示例指定不需要元素分隔符的日期格式。它们返回 64701 的日期内部值:
以下示例指定 YYYYMM 日期格式。它不需要元素分隔符。它为缺失的日期元素提供 01 ,返回日期 64800 (2018 年 6 月 1 日):
SQL基础教程(第2版)第8章 SQL高级处理:8-1 窗口函数
第8章 SQL高级处理:8-1 窗口函数
● 窗口函数可以进行排序、生成序列号等一般的聚合函数无法实现的高级操作。
● 理解PARTITION BY和ORDER BY这两个关键字的含义十分重要。
■ 什么是窗口函数
截至 2016 年 5 月,Oracle、SQL Server、DB2、PostgreSQL 的最新版本都已经支持了该功能,但是 MySQL 的5.7版本还是不支持窗口函数。
OLAP 是 OnLine Analytical Processing 的简称,意思是对数据库数据进行实时分析处理。 例如,市场分析、创建财务报表、创建计划等日常性商务工作。
窗口函数就是为了实现 OLAP 而添加的标准 SQL 功能。在Oracle和 SQL Server中称为分析函数。
■ 窗口函数的语法
窗口函数大体可以分为以下两种。
① 能够作为窗口函数的聚合函数( SUM、 AVG、 COUNT、 MAX、 MIN)
② RANK、 DENSE_RANK、 ROW_NUMBER 等专用窗口函数
■ 语法的基本使用方法——使用RANK函数
正如其名称所示, RANK 是用来计算记录排序的函数。
例如,对于之前使用过的 Product 表中的 8 件商品,让我们根据不同的商品种类(product_type),按照销售单价(sale_price)从低到高的顺序排序,结果如下所示。
PARTITION BY 在横向上对表进行分组,而 ORDER BY决定了纵向排序的规则。
ORDER BY 能够指定按照哪一列、何种顺序进行排序。可以通过关键字ASC/DESC 来指定升序和降序。
省略该关键字时会默认按照 ASC,也就是升序进行排序。
通过 PARTITION BY 分组后的记录集合称为窗口。此处的窗口并非“窗户”的意思,而是代表范围。
■ 无需指定PARTITION BY
使用窗口函数时起到关键作用的是 PARTITION BY 和 GROUP BY。
其中, PARTITION BY 并不是必需的,也就是将整个表作为一个大的窗口来使用。
■ 专用窗口函数的种类
● RANK函数
计算排序时,如果存在相同位次的记录,则会跳过之后的位次。
例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、4 位……
● DENSE_RANK函数
同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。
例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、2 位……
● ROW_NUMBER函数
赋予唯一的连续位次。
例)有 3 条记录排在第 1 位时:1 位、2 位、3 位、4 位……
除此之外,各 DBMS 还提供了各自特有的窗口函数。上述 3 个函数(对于支持窗口函数的 DBMS 来说)在所有的 DBMS 中都能够使用。
■ 窗口函数的适用范围
窗口函数只能书写在一个特定的位置,这个位置就是 SELECT 子句之中。
反过来说,就是这类函数不能在WHERE 子句或者 GROUP BY 子句中使用。
在 SELECT 子句之外“使用窗口函数是没有意义的”,所以在语法上才会有这样的限制。
■ 作为窗口函数使用的聚合函数
所有的聚合函数都能用作窗口函数,其语法和专用窗口函数完全相同。
在按照时间序列的顺序,计算各个时间的销售额总额等的时候,通常都会使用这种称为累计的统计方法。
使用其他聚合函数时的操作逻辑也和本例相同。例如,使用 AVG 来代替 SELECT 语句中的 SUM(代码清单 8-5)。
像这样以“自身记录(当前记录)”作为基准进行统计,就是将聚合函数当作窗口函数使用时的最大特征。
■ 计算移动平均
窗口函数就是将表以窗口为单位进行分割,并在其中进行排序的函数。
其实其中还包含在窗口中指定更加详细的汇总范围的备选功能,该备选功能中的汇总范围称为框架。
其语法如代码清单 8-6 所示,需要在 ORDER BY 子句之后使用指定范围的关键字。
●指定框架(汇总范围)
这里我们使用了 ROWS(“行”)和 PRECEDING(“之前”)两个关键
字,将框架指定为“截止到之前 ~ 行”,因此“ROWS 2 PRECEDING”
就是将框架指定为“截止到之前 2 行”,也就是将作为汇总对象的记录限
定为如下的“最靠近的 3 行”。
● 自身(当前记录)
● 之前1行的记录
● 之前2行的记录
也就是说,由于框架是根据当前记录来确定的,因此和固定的窗口不同,其范围会随着当前记录的变化而变化。
这样的统计方法称为移动平均(moving average)。由于这种方法在希望实时把握“最近状态”时非常方便,因此常常会应用在对股市趋势的实时跟踪当中。
使用关键字 FOLLOWING(“之后”)替换 PRECEDING,就可以指定“截止到之后 ~ 行”作为框架了。
●将当前记录的前后行作为汇总对象
具体来说,就是将如下 3 行作为汇总对象来进行计算
● 之前1行的记录
● 自身(当前记录)
● 之后1行的记录
■ 两个ORDER BY
OVER 子句中的 ORDER BY 只是用来决定窗口函数按照什么样的顺序进行计算的,对结果的排列顺序并没有影响。
那么,如何才能让记录切实按照 ranking 列的升序进行排列呢?
答案非常简单。那就是在 SELECT 语句的最后,使用 ORDER BY子句进行指定(代码清单 8-9)。这样就能保证 SELECT 语句的结果中
记录的排列顺序了,除此之外也没有其他办法了。
以上是关于第144章 SQL函数 TO_DATE(二)的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 to_date /to_char 函数的情况下比较 oracle sql 中的日期?
SQL-17 获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary