sql - 选择具有正确输出的行时出现逻辑错误
问题描述
我了解基础知识,但我是 DBMS 的新手,而且我正在学习一门课程。
这是作业问题:
使用下表编写查询以显示过去 40 个月的销售额:
SALEID SID SLDATE 1001 1 01-JAN-14 1002 5 02-JAN-14 1003 4 01-FEB-14 1004 1 01-MAR-14 1005 2 01-FEB-14 1006 1 01-JUN-15
我的查询是:
select count(sldate) as sale_count
from sale
where sldate >= add_months(sysdate, -40)
我得到的预期输出是:
SALE_COUNT
0
但我收到一条错误消息:
错误:您的查询输出与预期结果匹配,但存在逻辑错误。
我不确定我在哪里弄错了逻辑。
解决方案
“过去 40 个月”是模棱两可的。
对于“从日期 x 持续 n 个月意味着什么”有多种解释,而 oracle 的 add_months 对此并没有垄断(实际上大多数人会说它没有按预期工作,等到 30.06 再问有人'一个月前的日期是什么' :) )
假设今天是 4 月 20 日。“上个月”是否包括 3 月 15 日、20 日、21 日或 25 日?它包括4月2日吗?这取决于,有人可能会说“上个月”是从 3 月 21 日到 4 月 20 日。
有人可以说,从 01.03 到今天的“上个月”。
有人会说,“上个月”是从 01.04 开始的。有人会说,“上个月”是指整个三月,而不是四月的一天。
当“今天”接近月底时,情况会变得更加棘手,尤其是在三月份。
不要仅仅因为你无法读懂写作业的人的想法而对自己苛刻;)
我写了一个查询,显示不同的方法如何产生不同的结果。
CREATE OR REPLACE FUNCTION temp_can_subst_interval_months(p_date date, p_n_of_months number) RETURN NUMBER AS
V_date DATE;
BEGIN
V_Date := p_date - (NUMTOYMINTERVAL(p_n_of_months, 'month'));
RETURN 1;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
with all_days as (
select to_date('2016-01-01', 'YYYY-MM-DD') + (level - 1) as d
from dual
connect by level < 1462
),
all_days_2 as (
select d date_of_query_being_run,
add_months(d, -40)as min_date_your_approach,
add_months(d, -40) + 1 as min_date_your_approach_2, -- same, but exclude the first day
trunc(add_months(d, -40), 'mm') as min_date_whole_month,
case when temp_can_subst_interval_months(d, 40) = 1 then
d - (interval '40' month)
else null
end as min_date_interval_approach
from all_days ad
order by ad.d
)
select ads.*
from all_days_2 ads
;
最有趣的结果是当您的方法与区间方法不同时:
1(系统日期) 2(您的) 3 4 5(间隔) 31.01.2016 30.09.2012 01.10.2012 01.09.2012 29.02.2016 31.10.2012 01.11.2012 01.10.2012 29.10.2012 31.03.2016 30.11.2012 01.12.2012 01.11.2012 30.04.2016 31.12.2012 01.01.2013 01.12.2012 30.12.2012 29.06.2016 28.02.2013 01.03.2013 01.02.2013 30.06.2016 28.02.2013 01.03.2013 01.02.2013 31.08.2016 30.04.2013 01.05.2013 01.04.2013 30.09.2016 31.05.2013 01.06.2013 01.05.2013 30.05.2013 31.10.2016 30.06.2013 01.07.2013 01.06.2013 30.11.2016 31.07.2013 01.08.2013 01.07.2013 30.07.2013 31.01.2017 30.09.2013 01.10.2013 01.09.2013 28.02.2017 31.10.2013 01.11.2013 01.10.2013 28.10.2013 31.03.2017 30.11.2013 01.12.2013 01.11.2013 30.04.2017 31.12.2013 01.01.2014 01.12.2013 30.12.2013 29.06.2017 28.02.2014 01.03.2014 01.02.2014 30.06.2017 28.02.2014 01.03.2014 01.02.2014 31.08.2017 30.04.2014 01.05.2014 01.04.2014 30.09.2017 31.05.2014 01.06.2014 01.05.2014 30.05.2014 31.10.2017 30.06.2014 01.07.2014 01.06.2014 30.11.2017 31.07.2014 01.08.2014 01.07.2014 30.07.2014 31.01.2018 30.09.2014 01.10.2014 01.09.2014 28.02.2018 31.10.2014 01.11.2014 01.10.2014 28.10.2014 31.03.2018 30.11.2014 01.12.2014 01.11.2014 30.04.2018 31.12.2014 01.01.2015 01.12.2014 30.12.2014 29.06.2018 28.02.2015 01.03.2015 01.02.2015 30.06.2018 28.02.2015 01.03.2015 01.02.2015 31.08.2018 30.04.2015 01.05.2015 01.04.2015 30.09.2018 31.05.2015 01.06.2015 01.05.2015 30.05.2015 31.10.2018 30.06.2015 01.07.2015 01.06.2015 30.11.2018 31.07.2015 01.08.2015 01.07.2015 30.07.2015 31.01.2019 30.09.2015 01.10.2015 01.09.2015 28.02.2019 31.10.2015 01.11.2015 01.10.2015 28.10.2015 31.03.2019 30.11.2015 01.12.2015 01.11.2015 30.04.2019 31.12.2015 01.01.2016 01.12.2015 30.12.2015 30.06.2019 29.02.2016 01.03.2016 01.02.2016 31.08.2019 30.04.2016 01.05.2016 01.04.2016 30.09.2019 31.05.2016 01.06.2016 01.05.2016 30.05.2016 31.10.2019 30.06.2016 01.07.2016 01.06.2016 30.11.2019 31.07.2016 01.08.2016 01.07.2016 30.07.2016
旁注:
也许该表包含“未来预期销售额”之类的内容,他们希望您过滤掉比 sysdate 晚的日期;)?
推荐阅读
- sorting - Powerapps 结合 SortByColumns AddColumns GroupBy 和 If 条件
- python - 为什么我的 pygame 窗口不适合我的 4k(3840x2160) 显示器?pygame 窗口的比例:(3000x1500)
- java - 无法使用 Apache POI 从 Payara 服务器中的 ADF 应用程序实用地导出 Excel 文件
- java - 使用用户凭据通过 Microsoft Graph API 通过控制台应用发送电子邮件
- swift - 在 swift 中使用 WebRTC 的 iOS 屏幕共享 (ReplayKit)
- arrays - 在我的控制器数组中检索 1 个变量
- python - 如何在 Django 模板中使用垂直表创建动态标题
- javascript - 单击复选框后如何使我的动态表格行消失?
- javascript - 分组和升序,如何制作具有2个属性的对象数组?
- html - 链接到同一 html 页面中的特定部分