【问题标题】:Getting data for input date ranges on monthy basis每月获取输入日期范围的数据
【发布时间】:2020-11-10 12:32:07
【问题描述】:

在我的 Oracle 表中,我有 Date 和 Salary 列。我创建了一个传递开始日期和结束日期的 Java api。 从我的数据库中,我需要以每月工资列的总和来获取记录。 例如:输入是:- 开始日期:2019 年 1 月 5 日和结束日期:2019 年 3 月 13 日。它应该返回 3 条记录:

  1. 2019 年 1 月 5 日至 2019 年 2 月 4 日的工资总额,
  2. 2019 年 2 月 5 日至 2019 年 3 月 4 日的工资总额,
  3. 2019 年 3 月 5 日至 2019 年 3 月 13 日的工资总额。

需要帮助 提前谢谢

【问题讨论】:

  • 这里的逻辑是什么?它总是从开始日期开始以一个月为单位进行吗?例如,如果开始日期是 1 月 31 日怎么办?
  • 您是在问如何找到截止日期(2 月 5 日、3 月 5 日)或如何从 Oracle 检索数据? (对于一个 Stack Overflow 问题来说,两个都问太多了,那么你需要问两个问题。)
  • Ole,给定的截止日期,我们需要将给定的日期作为计费周期的开始数据。
  • Alex,如果开始日期是 1 月 31 日,那么结束日期应该是 2 月 27 日/28 日(基于年份)

标签: sql oracle date intervals


【解决方案1】:

根据与开始日期的距离(以月为单位)对行进行分组:

select sum(salary) -- probably also put some interval identification here
from t
where date_column between date '2019-01-05' and date '2019-03-13' -- put startDate and endDate here
group by trunc(months_between(date_column, date '2019-01-05')) -- put startDate here

【讨论】:

  • trunc() 是做什么的?我已经有一段时间没有使用 Oracle 了。
  • 嗨,Thomas,这个解决方案有效,但是当我们需要从 2 月 28 日到 3 月 21 日获取数据时,Months_between 没有返回正确的输出。因为上述方法返回的 2 月 28 日到 3 月 29 日的 diff 是 1,但理想情况下它应该是 '0'。因为下一个周期从 3 月 30 日开始
  • @Neeraj 你到底指的是三月的哪一天? (您输入了 21,然后输入了 29)无论如何,两个日期都会产生正确的结果 - select trunc(months_between(date '2019-02-28', date '2019-03-29')), trunc(months_between(date '2019-02-28', date '2019-03-21')) from dual; 如果它不适合您的需要,最好创建自己的 my_months_between 函数,而不是直接将一些极端情况写入 SQL。
  • @Tomas,这是一个错字。让我用以下查询解释一下: select FLOOR(MONTHS_BETWEEN ( date '2018-03-27',date '2018-02-28' )) from dual o/p : Current Month select FLOOR(MONTHS_BETWEEN ( date '2018-03) -28',date '2018-02-28' )) 来自双 o/p :下个月。但我需要的是我的周期应该是相同的,直到 2 月 28 日到 3 月 29 日。这些是开始日期是任何月份的某个最后日期时的一些极端情况
【解决方案2】:

我只需减去 4 天并提取月份:

select trunc(date - interval 4 day, 'MON') as yyyymm, sum(salary)
from t
group by trunc(date - interval 4 day, 'MON')
order by min(date);

trunc()'MON' 参数将日期截断到月初。您还可以将值转换为字符串:

select to_char(date - interval 4 day, 'YYYY-MM') as yyyymm, sum(salary)
from t
group by to_char(date - interval 4 day, 'YYYY-MM')
order by min(date);

【讨论】:

  • 嗨 Gordan,感谢您的解决方案,除了开始日是 1 月 29 日、1 月 30 日、1 月 31 日之外,这是有效的。这是我面临这种方法的问题
  • @Neeraj 。 . .代码减去四天。我不知道月底会有什么影响。但也许你应该问一个新的 问题,并澄清不同开始日期应该发生什么。这似乎很清楚地减去了四天。
  • 因为我预计每月周期,所以这些月结束日期的周期会有所不同
【解决方案3】:

java.time

如何找到截止日期:

    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("d-[MMMM][MMM]-uuuu", Locale.ENGLISH);
    
    String inputStartDate = "5-Jan-2019";
    String inputEndDate = "13-March-2019";
    
    LocalDate startDate = LocalDate.parse(inputStartDate, inputFormatter);
    LocalDate endDate = LocalDate.parse(inputEndDate, inputFormatter);
    
    LocalDate[] cutDates = startDate.datesUntil(endDate, Period.ofMonths(1))
            .toArray(LocalDate[]::new);
    
    System.out.println("Cut dates: " + Arrays.toString(cutDates));

输出是:

截止日期:[2019-01-05、2019-02-05、2019-03-05]

现在您可以查询您的 Oracle 数据库关于从一个截止日期(含)到下一个截止日期(不包括),最后从最后一个截止日期到您的结束日期(包括或不包括,取决于您的要求)的每个间隔。

如果开始日期是一个月的 29、30 或 31,结果可能会有点意外。例如:

    String inputStartDate = "31-Jan-2019";
    String inputEndDate = "9-April-2019";

截止日期:[2019-01-31、2019-02-28、2019-03-31]

一个挑战是解析您的日期,因为您有时会得到一个月份的缩写(Jan 而不是 January),有时是一个完整的月份名称(March,而不是 Mar)。格式模式字符串中的方括号表示可选部分,因此我们的格式化程序将接受通过MMMM 的完整月份名称或通过MMM 的缩写。

有关如何将您的 LocalDate 对象传递给 SQL,请参见底部的链接。

链接

【讨论】:

  • 您好,Ole,感谢您分享的方法,问题是我在 Oracle 部分处理这些日期,所以不能使用 Java 进行翻译。在数据库中获取开始日期和结束日期,在数据库中我写了任何逻辑
猜你喜欢
  • 1970-01-01
  • 2021-08-01
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 2017-02-23
  • 2019-05-13
相关资源
最近更新 更多