【问题标题】:How to Select data for the last 2 quarters from database using SQL?如何使用 SQL 从数据库中选择最近 2 个季度的数据?
【发布时间】:2013-07-29 17:50:23
【问题描述】:

我的数据库中有过去 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';

【问题讨论】:

  • 是 Oracle 还是 MySQL?你们都标记了。

标签: mysql sql oracle mysqldump toad


【解决方案1】:

更新

对于甲骨文:

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,我没有考虑到您是可能想要检索在fromto 日期值之间的 any 时间点落在指定日期范围内的 any 时间的行(在上一个日期的开头之间)季度和下一季度的开始。)

为了简化(目前),我将只考虑生效日期为from &lt; to 的情况。

可能的情况可以这样描述(相当粗略): 竖线代表drbdre(日期范围开始和结束) 小于号表示“effective_date_from”(edf) 大于号代表“effective_date_to”(edt) 破折号表示edfedt 之间的“有效”日期

      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

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

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

要处理考虑时间分量的日期时间:

  WHERE NOT ( effective_date_to < drb OR effective_date_from >= dre )

(生成drbdre(日期范围开始和日期范围结束)的表达式显示在我的原始答案中。)

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

使用内联视图来提供这些表达式,我们得到答案顶部的 SQL。

我之前搁置了一些古怪的案例,比如effective_date_from &gt; effective_date_to;您必须弄清楚这些行是否有效,以及应该返回这些行的条件。


原始答案:

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

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

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)的值在上一季度或当前季度内的行,我们只需将该日期列与上述两个表达式进行比较:

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

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

-- 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)

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


使用这些“开始日期”的一种稍微不同的方法是使用内联视图返回日期值;这给了我们一个可以测试的单独查询,我们可以为表达式分配列名。在这里,我为内联视图使用别名 dr(日期范围):

甲骨文

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

MySQL

FROM mytable t
JOIN ( SELECT MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-2 QUARTER AS bd_next_qtr
            , MAKEDATE(YEAR(NOW()),1) + INTERVAL QUARTER(NOW())-0 QUARTER AS bd_prev_qtr
     ) dr
  ON t.mydate >= dr.bd_prev_qtr
 AND t.mydate <  dr.bd_next_qtr

【讨论】:

  • 你是上天赐予的礼物,谢谢你的服务??
【解决方案2】:

你试过了吗:

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');

【讨论】:

  • -1。这些表达式返回的日期值不保证在“季度”边界(1/1、4/1、6/1、9/1)上。 (其中一个保证不会,因为日期相隔 2 个月。)这不符合 OP 规范。
【解决方案3】:

我会得到你第一季度的开始日期 (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)
;

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

【讨论】:

    猜你喜欢
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    相关资源
    最近更新 更多