选择具有正确输出的行时发生逻辑错误

时间:2019-06-13 11:20:06

标签: sql database oracle rdbms

我了解基本知识,但是我是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

但是我收到一条错误消息:

  

错误:您的查询输出符合预期结果,但是存在逻辑错误。

我不确定我在哪里弄错了逻辑。

1 个答案:

答案 0 :(得分:1)

“过去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开始。 有人可以说,“上个月”意味着整个游行,而不是4月的一天。

当“今天”接近月底时,尤其是在三月,它变得更加棘手。

不要因为自己读不懂写作业的人而对自己发硬;)

我写了一个查询,显示了不同的方法如何产生不同的结果。

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 (sysdate) 2 (yours)   3           4           5 (interval)
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晚的日期;)?