【问题标题】:Postgresql, add (years, months or days) to date based on another columnPostgresql,根据另一列添加(年、月或日)日期
【发布时间】:2014-09-17 10:45:13
【问题描述】:

我需要来自 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 + 年”为例,它可以工作,但我也需要它像“1 + 月”和“1 + 天”一样动态工作。

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 天”

你有什么想法可以帮忙吗?

【问题讨论】:

    标签: sql postgresql date add


    【解决方案1】:

    每次您需要使用外部表进行日期运算时,请避免使用 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 的天数计算不起作用。

    【讨论】:

    • 是的,刚刚意识到。谢谢,我使用 tsnorri 方式获取 WARRANTY_ENDS 列,并使用您的方式获取 'DAYS' 列,效果很好。谢谢!
    【解决方案2】:

    我现在没有安装 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;
    

    【讨论】:

    • 效果很好!但是,我意识到最后一栏(天栏)我错了。它不计算日期之间的天数,只计算日期之间的天数。我将代码中的 created_at 替换为您的“WARRANTY_ENDS”列。它只从 -30 到 30。你知道如何解决它吗?
    • 我使用了 clodaldo neto 的解决方案来修复“DAYS”列,它现在可以正常工作了。谢谢你们!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多