oracle怎么求当年指定月的某天呢

比如说今天是2023/3/27,sql怎么得出的结果是2023/1/27 2023/2/27 2023/3/27这几个呢,也就是同年(2023年),月份小于等于3月,日等于27,如果是月份最后一天的话,如2023/3/31则得出的结果是2023/1/31 2023/2/28 2023/3/31也就是各个月的最后一天,请问SQL怎么写呢

SELECT
    CASE 
        WHEN MONTH(LAST_DAY('2023/3/27')) < 3 THEN DATE_FORMAT('2023/3/27', '%Y/1/%d')
        WHEN MONTH(LAST_DAY('2023/3/27')) = 3 THEN DATE_FORMAT('2023/3/27', CONCAT('%Y/2/', IF(DAY(LAST_DAY('2023/3/27')) = 31, '28', '27')))
        ELSE DATE_FORMAT('2023/3/27', '%Y/%m/27')
    END AS 'Result'

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7722507
  • 这篇博客你也可以参考下:Oracle数据库中如何获取当前年下的01- 12 个月 并用1/12 -12/12
  • 除此之外, 这篇博客: Oracle 数据库(六)—— Oracle SQL语言之用户模式、简单查询、条件查询、分组查询和排序查询中的 3.4 分组查询 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 3.4.1 分组查询介绍
    数据分组的目的是用来汇总数据或为整个分组显示单行的汇总信息,通常在查询结果集中使用GROUP BY子句对记录进行分组。

    在SELECT语句中,GROUP BY子句位于FROM子句之后,其语法格式如下:

    SELECT columns_list
      FROM table_name
    [WHERE conditional_expression]
    GROUP BY columns_list
    
    • columns_list:字段列表,在GROUP BY子句中也可以指定多个列分组。  table_name:表名。
    • conditional_expression:筛选条件表达式。
    • GROUP BY子句可以基于指定某一列的值将数据集合划分为多个分组,同一组内所有记录在分组属性上具有相同值,也可以基于指定多列的值将数据集合划分为多个分组。

    **3.4.2 使用GROUP BY进行单列分组 **
    单列分组是指基于列生成分组统计结果,当进行单列分组时,会基于分组列的每个不同值生成一个统计结果。

    select deptno, job from emp group by deptno, job order by deptno;
    

    GROUP BY子句经常与聚集函数一起使用。使用GROUP BY子句和聚集函数,可以实现对查询结果中每一组数据进行分类统计。所以,在结果中每组数据都有一个与之对应的统计值。在Oracle系统中,经常使用的统计函数如图所示。
    在这里插入图片描述

    select job, sum(sal) from emp group by job;
    

    查询结果

    JOB                  SUM(SAL)
    ------------------ ----------
    CLERK                    4150
    SALESMAN                 5600
    PRESIDENT                5000
    MANAGER                  8275
    ANALYST                  6000
    

    在使用GROUP BY子句时,要注意:

    • SELECT子句的后面只可以有两类表达式:统计函数和进行分组的列名。
    • 在SELECT子句中的列名必须是进行分组的列,除此之外添加其他的列名都是错误的,但是GROUP BY子句后面的列名可以不出现在SELECT子句中。
    • 在默认情况下,将按照GROUP BY子句指定的分组列升序排列,如果需要重新排序,可以使用ORDER BY子句指定新的排列顺序。

    GROUP BY子句中的列可以不在SELECT列表中。

    select sum(sal) from emp group by job;
    

    查询结果

       SUM(SAL)
    ----------
          4150
          5600
          5000
          8275
          6000
    

    3.4.3 使用GROUP BY进行多列分组
    多列分组是指基于两个或两个以上的列生成分组统计结果。当进行多列分组时,会基于多个列的不同值生成统计结果。

    select deptno, job, avg(sal), max(sal) from emp group by deptno, job;
    

    3.4.4 使用ORDER BY改变分组排序结果
    当使用GROUP BY子句执行分组统计时,会自动基于分组列进行升序排列。为了改变分组数据的排序结果,需要使用ORDER BY子句。

    select deptno,sum(sal) from emp group by deptno order by sum(sal) desc;
    

    3.4.5 使用HAVING子句限制分组结果
    HAVING子句通常与GROUP BY子句一起使用,在完成对分组结果统计后,可以使用HAVING子句对分组的结果做进一步的筛选。

    如果不使用GROUP BY子句,HAVING子句的功能与WHERE子句一样。HAVING子句和WHERE子句的相似之处都是定义搜索条件,唯一不同的是HAVING子句中可以包含聚合函数,如常用的(count)、(avg)、(sum)等,在WHERE子句中则不可以使用聚合函数。

    • 如果在SELECT语句中使用了GROUP BY子句,那么HAVING子句将应用于GROUP BY子句创建的那些组。
    • 如果指定了WHERE子句,而没有指定GROUP BY子句,那么HAVING子句将应用于WHERE子句的输出,并且整个输出被看作一个组.
    • 如果在SELECT语句中既没有指定WHERE子句,也没有指定GROUP BY子句,那么HAVING子句将应用于FROM子句的输出,并且将其看作一个组。
    select deptno as  部门编号,
           avg(sal) as  平均工资 
      from emp 
    group by deptno 
    having avg(sal) > 2000 ;
    

    在这里插入图片描述上面的示例无法使用WHERE子句直接过滤出平均工资大于2000的部门信息,因为在WHERE子句中不可以使用聚合函数(这里是AVG)。

    通常情况下,HAVING子句与GROUP BY子句一起使用,这样可以汇总相关数据后再进一步筛选汇总的数据。

    3.4.6 在GROUP BY中使用ROLLUP和CUBE操作符
    默认情况下,当使用GROUP BY子句生成数据统计结果时,只会生成相关列的数据统计信息,而不会生成小计和总计统计。

    在实际应用程序中,不仅需要获得以上统计结果,而且可能还需要取得横向、纵向小计统计以及总计统计,例如部门的平均工资、岗位的平均工资、所有雇员的平均工资等。为了取得更全面的数据统计,可以使用ROLLUP和CUBE操作符。

    (1)使用ROLLUP操作符执行数据统计

    当使用ROLLUP操作符时,在保留原有统计结果的基础上,还会生成横向小计和总计。

    select deptno as  部门编号, 
    	   job as  岗位, 
    	   avg(sal) as  平均工资
      from emp 
    group by rollup(deptno,job) ;
    

    在这里插入图片描述(2)使用CUBE操作符执行数据统计

    当使用CUBE操作符时,在保留原有统计结果的基础上,还会生成横向小计、纵向小计岗位平均工资和总计。

    select deptno as  部门编号, 
    	   job as  岗位, 
    	   avg(sal) as  平均工资
      from emp 
    group by cube(deptno,job) ;
    

    在这里插入图片描述(3)使用GROUPING函数

    当使用ROLLUP或者CUBE操作符生成统计结果时,某个统计结果行可能用到一列或者多列,也可能没有使用任何列。为了确定统计结果是否使用了特定列,可以使用GROUPING函数。如果该函数返回0,则表示统计结果使用了该列;如果函数返回1,则表示统计结果没有使用该列。

    select deptno,job, sum (sal),grouping(deptno),grouping(job)
      from emp 
    group by rollup(deptno,job) ;
    

    在这里插入图片描述
    (4)在ROLLUP操作符中使用复合列

    复合列被看作一个逻辑单元的列组合,当引用复合列时,需要用括号括住相关列。通过在ROLLUP操作符中使用复合列,可以略过ROLLUP操作符的某些统计结果。

    例如,子句GROUP BY ROLLUP(a,b,c)的统计结果等同于GROUP BY(a,b,c)、GROUP BY(a,b)、GROUP BY a以及GROUP BY ( )的并集;而如果将(b,c)作为复合列,那么子句GROUP BY ROLLUP(a,(b,c))的结果等同于GROUP BY(a,b,c)、GROUP BY a以及GROUP BY ()的并集。

    select deptno,job, sum (sal)
      from emp 
    group by rollup((deptno,job)) ;
    

    在这里插入图片描述
    6.使用GROUPING SETS操作符

    GROUPING SETS操作符是GROUP BY子句的进一步扩展。在Oracle Database 9i之前,使用GROUP BY子句一次只能显示单种分组结果,如果要生成多种分组统计结果,那么需要编写多条SELECT分组语句。从Oracle Database 9i开始,通过使用GROUPING SETS操作符,可以合并多个分组的统计结果,从而简化了多个分组操作。

    select deptno, job, avg (sal)  
      from emp 
    group by grouping sets(deptno,job);
    

    在这里插入图片描述

  • 您还可以看一下 黄利强老师的Oracle从入门到精通全套视频教程之备份恢复与数据迁移课程中的 数据库冷备份异机恢复实战演示课小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    针对优化后的问题,可以使用如下的SQL查询语句来解决:

    SELECT TO_CHAR(DATE_COL, 'yyyy-MM-dd') AS MONTHLY_DATE
    FROM (
        SELECT TRUNC(TO_DATE('2023-01-01', 'yyyy-MM-dd'), 'MM') + LEVEL - 1 AS DATE_COL
        FROM DUAL
        CONNECT BY LEVEL <= 12
    )
    WHERE DATE_COL = LAST_DAY(DATE_COL) OR TO_CHAR(DATE_COL, 'dd') = '27'
    

    解释如下:

    1. 首先使用 TRUNC 函数将给定年份的1月1日转换为日期格式(使用 TO_DATE 函数),同时返回该月的第一天,接着使用 LEVEL 函数加上月份对应的序号,从而生成每个月的第一天。这里使用了 DUAL 表和 CONNECT BY 语句,以生成包含12个日期的虚拟表。

    2. 对于每个月的第一天,通过 LAST_DAY 函数可以计算出这个月的最后一天,而使用 TO_CHAR 函数可以将日期转换为字符串格式,从而获取这个月的最后一天的日期字符串。

    3. 还需要检查每个月是否存在27日,可以通过 TO_CHAR 函数将日期转换为字符串,并且使用 dd 格式化标识符来提取月份的日期部分。如果这个日期为27,则将其保存下来。

    4. 最终的结果是通过将每个月的最后一天和27号合并起来,在一个总的结果集中返回。我们使用外部查询语句来检查每个月的日期是否符合要求,并用 TO_CHAR 函数将它们转换为字符串,这样可以使用一个 SELECT 语句来返回结果集。

    需要说明的是,这个查询语句的关键是使用了 CONNECT BY 语句和 LEVEL 函数来生成一列日期,然后使用各种函数来操作这些日期,从而得到符合要求的结果。需要特别注意的是,在Oracle数据库中,我们可以使用 DUAL 表来生成虚拟的行数据,DUAL 表只有一行,但是通过 CONNECT BY 语句可以不断生成更多的行,这样可以避免使用外部数据源,并且可以方便地生成任意数量的数据行。


SELECT 
to_char(ADD_MONTHS(SYSDATE,-2),'yyyy/mm/dd'),
to_char(ADD_MONTHS(SYSDATE,-1),'yyyy/mm/dd'),
to_char(SYSDATE,'yyyy/mm/dd')
FROM dual