如何使用SQL从数据库中选择最近2个季度的数据?

时间:2013-07-29 17:50:24

标签: mysql sql oracle mysqldump toad

我在我们的数据库中有过去2年的模型数据。我想从数据库表中仅选择最后2个季度的那些模型。

假设Sysdate-> 29/07/2013(July)

我应该可以从下面的季度中检索模型

Q1-April,May,June(last quarter)

Q2-July,Aug,Sep(Including quarter)

以下查询需要如何更改?

Select model_id,model_name,Effective_date_from,effective_date_to 
from   model 
where active='YES';

3 个答案:

答案 0 :(得分:5)

<强>更新

对于Oracle:

FROM mytable t
JOIN ( SELECT ADD_MONTHS(TRUNC(SYSDATE,'Q'),3) AS b
            , ADD_MONTHS(TRUNC(SYSDATE,'Q'),-3) AS e
         FROM DUAL
     ) dr
  ON NOT ( t.effective_date_from >= dr.e OR t.effective_date_to < dr.b )
  OR ( t.effective_date_from IS NULL AND t.effective_date_to IS NULL )

对于MySQL:

FROM mytable t
JOIN ( SELECT MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-2 QUARTER AS b
            , MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-0 QUARTER AS e
     ) dr
  ON NOT ( t.effective_date_from >= dr.e OR t.effective_date_to < dr.b )
  OR ( t.effective_date_from IS NULL AND t.effective_date_to IS NULL )

在审核了slOppy的回答并再次回顾问题后,我意识到您有两个日期列,effective_date_fromeffective_date_to,并且我没有考虑到您可能想要检索<{1}}和from日期值之间的任何时间点的行在您指定日期内任何时间的帐户范围(在上一季度开始和下一季度开始之间。)

为了简化(现在),我将仅考虑生效日期to的情况。

可能的情况(相当粗略地)描述了这样的事情:      垂直条代表from < todrb(日期范围的开始和结束)      小于号表示“dre”(effective_date_from)      大于号表示“edf”(effective_date_to)      破折号代表edtedf

之间的“有效”日期
edt

我认为你要求返回满足案例2到5以及边缘情况e1到e6的行,这是案例1,6和e7的所有情况除外。

如果我们可以编写一个测试案例1和6的谓词,然后否定它,它应该给我们你想要的东西。像这样:

处理考虑了时间成分的日期时间:

      drb     dre
<--->  |       |              case 1: edt < drb
   <---|---->  |              case 2: drb between edf and edt
    <--|-------|---->         case 3: edf < drb AND edt > dre
       | <---> |              case 4: edf > drb AND edt < dre
       |    <--|--->          case 5: edf between drb and dre AND edt > dre
       |       |  <--->       case 6: edf > dre
       |       |
   <--->       |              case e1: edt = drb
    <--|------->              case e2: edf > drb AND edt = dre
       <--->   |              case e3: edf = drb and edt < dre
       <------->              case e4: edf = drb and edt = dre
       <-------|-->           case e5: edf = drb and edt > dre
       |   <--->              case e6: edf > drb AND edt = dre
       |       <--->          case e7: edf = dre

(生成 WHERE NOT ( effective_date_to < drb OR effective_date_from >= dre ) drb的表达式(日期范围开始和日期范围结束)显示在我的原始答案中。)

要同时返回dreeffective_date_from都为NULL的行,我们可以添加一个单独的条件来处理这种情况。

使用内联视图提供这些表达式,我们将SQL放在答案的顶部。

我之前搁置了奇怪的案例,例如effective_date_to;你必须弄清楚这些行是否有效,以及应该返回这些行的条件。


原始答案:

这可以在 Oracle MySQL 中实现。我使用的方法是首先生成每个季度的“开始日期”,相对于当前日期。我们可以在谓词中引用那些日期值(或返回日期值的表达式)。

要在 MySQL 中推导出四分之一的“开始日期”,我们可以使用effective_date_from > effective_date_to函数。 (此函数从指定的DATE值返回1到4的整数值。结合QUARTER()和MAKEDATE函数,我们可以生成当前系统日期的每个相对季度的“开始日期”,如下所示:

YEAR

一旦我们拥有这些日期值,就会很简单。要仅获取特定日期列(以下示例中为SELECT MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-0 QUARTER AS next_q , MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-1 QUARTER AS this_q , MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-2 QUARTER AS prev_q next_q this_q prev_q ---------- ---------- ------------ 2013-10-01 2013-07-01 2013-04-01 )的值具有属于上一季度或当前季度的值,我们只需将该日期列与上述两个表达式进行比较:

mydate

Oracle 中,方法是一样的。不同之处在于我们如何推导出相对季度的开始日期。在Oracle中,我们可以使用以下表达式:

WHERE mydate >= MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-2 QUARTER
  AND mydate <  MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-0 QUARTER

因此,要获取-- ALTER SESSION SET nls_date_format = 'YYYY-MM-DD'; SELECT ADD_MONTHS(TRUNC(SYSDATE,'Q'),3) AS next_q , ADD_MONTHS(TRUNC(SYSDATE,'Q'),0) AS this_q , ADD_MONTHS(TRUNC(SYSDATE,'Q'),-3) AS prev_q FROM DUAL NEXT_Q THIS_Q PREV_Q ---------- ---------- ------------ 2013-10-01 2013-07-01 2013-04-01 的值在当前或上一季度的行,我们将该列与其中两个表达式进行比较:

mydate

(大于或等于上一季度的开始日期,并且小于下一季度的开始日期)。


使用这些“开始日期”的略有不同的方法是使用内联视图返回日期值;这为我们提供了一个可以测试的单独查询,我们可以为表达式分配列名。在这里,我使用别名WHERE mydate >= ADD_MONTHS(TRUNC(SYSDATE,'Q'),-3) AND mydate < ADD_MONTHS(TRUNC(SYSDATE,'Q'),3) (日期范围)作为内联视图:

<强>的Oracle

dr

<强>的MySQL

FROM mytable t
JOIN ( SELECT ADD_MONTHS(TRUNC(SYSDATE,'Q'),3) AS bd_next_qtr
            , ADD_MONTHS(TRUNC(SYSDATE,'Q'),-3) AS bd_prev_qtr
         FROM DUAL
     ) dr
  ON t.mydate >= dr.bd_prev_qtr
 AND t.mydate <  dr.bd_next_qtr

答案 1 :(得分:1)

你有没有尝试过:

SELECT
    * 
FROM
    yourTable
WHERE 
    yourDate  >= DATE_FORMAT( CURRENT_DATE - INTERVAL 3 MONTH, '%Y/%m/01' ) 
AND
    yourDate  < DATE_FORMAT( CURRENT_DATE- INTERVAL 1 MONTH, '%Y/%m/01');

答案 2 :(得分:1)

我会得到你第一季度的开始日期(min_date)和第二季度的结束日期(max_date)以获得适当的范围,然后执行以下操作:

SELECT model_id,model_name,Effective_date_from,effective_date_to 
FROM model 
WHERE active='YES'
 AND (Effective_date_from BETWEEN min_date AND max_date OR effective_date_to BETWEEN min_date AND max_date)
;

这应该会为您提供在这两个季度中某些时候处于活动状态的模型。