Postgresql,根据另一列添加(年,月或日)到目前为止

时间:2014-07-25 14:28:46

标签: sql postgresql date add

我需要从8.4 POSTGRESQL数据库中查询,以按照代表产品保修结束的实际日期的日期列出我订购的所有产品。

表格是这样的,我会说得很简单:

PRODUCT (varchar) 
WARRANTY (int)
TYPE_WARRANTY (char) ( 'Y', 'M', 'D' ) -- Years, Months or Days
CREATED_AT (date)

举个例子:

PRODUCT  |  WARRANTY  |  TYPE_WARRANTY  |  CREATED_AT 
------------------------------------------------------
'PROD A' |      1     |       'Y'       | '2014-01-01'
'PROD B' |     10     |       'M'       | '2014-06-01'
'PROD C' |     30     |       'D'       | '2014-01-01'

我需要的是一个会给我带来这个问题的查询:

PRODUCT  |  WARRANTY  |  TYPE_WARRANTY  |  CREATED_AT  | WARRANTY_ENDS | DAYS
-----------------------------------------------------------------------------
'PROD C' |    30      |       'D'       | '2014-01-01' | '2014-01-31'  | -175
'PROD A' |     1      |       'Y'       | '2014-01-01' | '2015-01-01'  | 160
'PROD B' |    10      |       'M'       | '2014-06-01' | '2015-04-01'  | 250

我希望你能理解它

所以我需要的是选择所有产品并在保修期结束时订购,包括今天和该日期之间的天数。

我已经拥有的东西:

我知道如何获取日期,我知道如何将日期添加到日期,我现在需要的是一种使查询理解我想根据type_warranty列的值添加间隔的方法。

我在这里使用'1 + year'作为例子并且它有效,但我需要动态工作,如'1 +月'和'1 + day'。

SELECT 
  PRODUCT, WARRANTY, TYPE_WARRANTY, CREATED_AT, 
  (CREATED_AT + (WARRANTY * '1 year'::INTERVAL)) as WARRANTY_ENDS,
  EXTRACT(day from age((CREATED_AT + '1 year', current_date)) as days
FROM TABLE
order by days; 

这有效,但只有多年,当然,我不知道如何将'1年'转换为'1个月'或'1天',具体取决于warranty_type

你有任何想法可以提供帮助吗?

2 个答案:

答案 0 :(得分:4)

每次需要使用外表进行日期算术时,避免case的笨拙。在这个例子中,它是一个CTE表,但它应该是真实的。或者只需将WARRANTY列更改为interval

with itval (type_warranty, itvalue) as (
    values ('D', '1 day'::interval), ('M', '1 month'), ('Y', '1 year')
)
select 
    product,
    warranty,
    type_warranty,
    created_at, 
    created_at + (warranty * itvalue) as warranty_ends,
    (created_at + (warranty * itvalue))::date - current_date as days
from
    t
    inner join
    itval using (type_warranty)
order by days;

基于extractage的日算不起作用。

答案 1 :(得分:3)

我现在没有安装PostgreSQL 8.4,但这有用吗?

SELECT
    PRODUCT, WARRANTY, TYPE_WARRANTY, CREATED_AT, 
    (CREATED_AT + (WARRANTY *
        CASE TYPE_WARRANTY
            WHEN 'Y' THEN '1 year'::interval
            WHEN 'M' THEN '1 month'::interval
            WHEN 'D' THEN '1 day'::interval
        END
    ))::date as WARRANTY_ENDS,
    (created_at + (warranty * itvalue))::date - current_date as days
    FROM TABLE;