将 crystal 报告代码转换为 Oracle SQL 日期范围查询
Converting crystal report code to Oracle SQL query for date range
我有一个 crystal 报告日期范围,用于一段时间 sheet。 (我继承的东西)我正在寻求帮助,了解如何将其更改为我的 sql 从 Oracle 查询 SSRS 报告的一部分
Today - Round((((Today - Date (1998,11,23 ))/14) - Truncate((Today - Date (1998,11,23 ))/14)) * 14,0)
提前致谢
史蒂文(他对 sql 和 ssrs 报告还是很陌生)
你的直接翻译好像是:
trunc(sysdate) - round((((trunc(sysdate) - date '1998-11-23')/14) - trunc((trunc(sysdate) - date '1998-11-23')/14)) * 14,0)
但您可以将其简化为:
trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
这两个 trunc(sysdate)
调用给出了当前日期,时间被截断为午夜,因此当前为 2016-02-12。如果你减去你的固定开始日期(大概是你系统中的第一个时期?)你会得到一个数字,from how Oracle does datetime arithmetic:
select trunc(sysdate) - date '1998-11-23' from dual;
TRUNC(SYSDATE)-DATE'1998-11-23'
---------------------------------------
6290
因为两个日期都在午夜,所以它是一个整数 - 今天和固定日期之间的天数。如果将其除以 14,则得到 449.285,即整整两周的 449 个周期,当前周期的 0.285。您的原始计算采用它并删除了截断版本 449 以仅保留 .285,然后将其乘以 14 以将剩余部分作为整数返回,即 4。
但这正是 the mod()
function 给你的 - "the remainder of n2 divided by n1"。换句话说,mod(6290, 14)
是 6290 除以 14 的余数,也就是 4。它从一个表达式而不是两个表达式得到相同的结果。
那么您只需从当天减去计算出的值 4,今天就可以追溯到 2016 年 2 月 8 日。
查看所选生成日期的变化情况:
with t (dt) as (
select trunc(sysdate) - level from dual connect by level < 21
)
select dt,
dt - round((((dt - date '1998-11-23')/14) - trunc((dt - date '1998-11-23')/14)) * 14) long_version,
dt - mod(dt - date '1998-11-23', 14) period_start,
dt - mod(dt - date '1998-11-23', 14) + 14 period_end
from t
order by dt;
DT LONG_VERSION PERIOD_START PERIOD_END
---------- ------------ ------------ ----------
2016-01-23 2016-01-11 2016-01-11 2016-01-25
2016-01-24 2016-01-11 2016-01-11 2016-01-25
2016-01-25 2016-01-25 2016-01-25 2016-02-08
2016-01-26 2016-01-25 2016-01-25 2016-02-08
...
2016-02-06 2016-01-25 2016-01-25 2016-02-08
2016-02-07 2016-01-25 2016-01-25 2016-02-08
2016-02-08 2016-02-08 2016-02-08 2016-02-22
2016-02-09 2016-02-08 2016-02-08 2016-02-22
2016-02-10 2016-02-08 2016-02-08 2016-02-22
2016-02-11 2016-02-08 2016-02-08 2016-02-22
您可以通过在结果中添加天数来获得期末,或者使用 14 天后的开始日期单独计算。如果你正在寻找一个范围内的记录,你可以这样做:
where some_date >= trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
and some_date < trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14) + 14
如果 none 个日期有午夜后的时间(时间表可能就是这种情况),您可以使用 between
并按照您的建议使时间段在 13 天后结束您目前在评论中所做的事情:
where some_date between trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
and trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14) + 13
虽然我更喜欢 >= 和 < 方法,因为当你在数据上做一些时间也很重要的事情时,它不会绊倒你。
我有一个 crystal 报告日期范围,用于一段时间 sheet。 (我继承的东西)我正在寻求帮助,了解如何将其更改为我的 sql 从 Oracle 查询 SSRS 报告的一部分
Today - Round((((Today - Date (1998,11,23 ))/14) - Truncate((Today - Date (1998,11,23 ))/14)) * 14,0)
提前致谢 史蒂文(他对 sql 和 ssrs 报告还是很陌生)
你的直接翻译好像是:
trunc(sysdate) - round((((trunc(sysdate) - date '1998-11-23')/14) - trunc((trunc(sysdate) - date '1998-11-23')/14)) * 14,0)
但您可以将其简化为:
trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
这两个 trunc(sysdate)
调用给出了当前日期,时间被截断为午夜,因此当前为 2016-02-12。如果你减去你的固定开始日期(大概是你系统中的第一个时期?)你会得到一个数字,from how Oracle does datetime arithmetic:
select trunc(sysdate) - date '1998-11-23' from dual;
TRUNC(SYSDATE)-DATE'1998-11-23'
---------------------------------------
6290
因为两个日期都在午夜,所以它是一个整数 - 今天和固定日期之间的天数。如果将其除以 14,则得到 449.285,即整整两周的 449 个周期,当前周期的 0.285。您的原始计算采用它并删除了截断版本 449 以仅保留 .285,然后将其乘以 14 以将剩余部分作为整数返回,即 4。
但这正是 the mod()
function 给你的 - "the remainder of n2 divided by n1"。换句话说,mod(6290, 14)
是 6290 除以 14 的余数,也就是 4。它从一个表达式而不是两个表达式得到相同的结果。
那么您只需从当天减去计算出的值 4,今天就可以追溯到 2016 年 2 月 8 日。
查看所选生成日期的变化情况:
with t (dt) as (
select trunc(sysdate) - level from dual connect by level < 21
)
select dt,
dt - round((((dt - date '1998-11-23')/14) - trunc((dt - date '1998-11-23')/14)) * 14) long_version,
dt - mod(dt - date '1998-11-23', 14) period_start,
dt - mod(dt - date '1998-11-23', 14) + 14 period_end
from t
order by dt;
DT LONG_VERSION PERIOD_START PERIOD_END
---------- ------------ ------------ ----------
2016-01-23 2016-01-11 2016-01-11 2016-01-25
2016-01-24 2016-01-11 2016-01-11 2016-01-25
2016-01-25 2016-01-25 2016-01-25 2016-02-08
2016-01-26 2016-01-25 2016-01-25 2016-02-08
...
2016-02-06 2016-01-25 2016-01-25 2016-02-08
2016-02-07 2016-01-25 2016-01-25 2016-02-08
2016-02-08 2016-02-08 2016-02-08 2016-02-22
2016-02-09 2016-02-08 2016-02-08 2016-02-22
2016-02-10 2016-02-08 2016-02-08 2016-02-22
2016-02-11 2016-02-08 2016-02-08 2016-02-22
您可以通过在结果中添加天数来获得期末,或者使用 14 天后的开始日期单独计算。如果你正在寻找一个范围内的记录,你可以这样做:
where some_date >= trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
and some_date < trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14) + 14
如果 none 个日期有午夜后的时间(时间表可能就是这种情况),您可以使用 between
并按照您的建议使时间段在 13 天后结束您目前在评论中所做的事情:
where some_date between trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
and trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14) + 13
虽然我更喜欢 >= 和 < 方法,因为当你在数据上做一些时间也很重要的事情时,它不会绊倒你。