我在我们的数据库中有过去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';
答案 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_from
和effective_date_to
,并且我没有考虑到您可能想要检索<{1}}和from
日期值之间的任何时间点的行在您指定日期内任何时间的帐户范围(在上一季度开始和下一季度开始之间。)
为了简化(现在),我将仅考虑生效日期to
的情况。
可能的情况(相当粗略地)描述了这样的事情:
垂直条代表from < to
和drb
(日期范围的开始和结束)
小于号表示“dre
”(effective_date_from
)
大于号表示“edf
”(effective_date_to
)
破折号代表edt
和edf
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
的表达式(日期范围开始和日期范围结束)显示在我的原始答案中。)
要同时返回dre
和effective_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)
;
这应该会为您提供在这两个季度中某些时候处于活动状态的模型。