【问题标题】:Using DATE_ADD with a Column Name as the Interval Value将 DATE_ADD 与列名称一起用作间隔值
【发布时间】:2014-03-14 11:38:35
【问题描述】:

我有一个包含产品、开始日期和间隔值的表格:

product_name                    start_date              expiry_period
Domain Registration (1 Year)    2013-12-08 00:00:00     1 Year
Domain Registration (1 Year)    2013-12-01 00:00:00     1 Year
Website Hosting (Bronze)        2013-12-19 00:00:00     1 Year
Website Hosting (Silver)        2013-12-20 00:00:00     1 Year
Website Hosting (Silver)        2013-12-21 00:00:00     1 Year
Domain Registration (2 years)   2014-01-04 00:00:00     2 Year
Domain Registration (1 Year)    2014-01-04 00:00:00     1 Year
Website Hosting (Silver)        2014-01-06 00:00:00     1 Year
Domain Registration (2 years)   2014-01-06 00:00:00     2 Year
Domain Registration (1 Year)    2014-01-07 00:00:00     1 Year
Domain Registration (1 Year)    2014-01-10 00:00:00     1 Year
Website Hosting (Bronze)        2014-01-12 00:00:00     1 Year

我正在尝试在我的选择语句中添加一个计算值,以将间隔添加到 start_date,以便我的数据集以编程方式返回开始日期和结束日期。

这是我目前拥有的:

select 
    product_name, 
    start_date,
    expiry_period
    DATE_ADD(start_date, INTERVAL expiry_period) as end_date
from
    tbl_products

但是,它针对 DATE_ADD 行返回错误(SQL 语法不正确)。

我读过的所有 SO 文章似乎都表明表达式和类型需要分开(即DATE_ADD(start_date, INTERVAL expiry_value expiry_type)) - 当然不是这样,我可以在一个单曲中传递一个句点领域?

如果不是,并且由于我无法更改数据架构,那么推荐的方法是什么?我曾考虑使用SUBSTRING_INDEX 来拆分列,但这似乎也不起作用。

【问题讨论】:

  • 你的区间限定符是否总是Year
  • 不,它可以是任何东西 - 日/周/月/年。只是我的样本数据集最重要的是“年份”

标签: mysql sql dateadd


【解决方案1】:

得到你的结果并不容易 - 因为你将它存储为普通的1 Year 或类似的。 不允许INTERVAL 构造中动态使用它 - MySQL 语法 demands 您将同时指出区间数量和类型。

但是,有一种技巧可以解决这个问题:

SELECT 
    product_name, 
    start_date,
    expiry_period,
    @num:=CAST(expiry_period AS UNSIGNED),
    @p  :=SUBSTR(expiry_period, CHAR_LENGTH(@num)+2),
    CASE
      WHEN @p='Year' THEN DATE_ADD(start_date, INTERVAL @num YEAR)
      WHEN @p='Month' THEN DATE_ADD(start_date, INTERVAL @num MONTH)
      WHEN @p='Day' THEN DATE_ADD(start_date, INTERVAL @num DAY)
      WHEN @p='Week' THEN DATE_ADD(start_date, INTERVAL @num WEEK)
    END AS end_date
FROM
    tbl_products

-如您所见,此查询依赖于事实,即数量总是在前(因此CAST 将准确提取它,因此,它可用于在此之后获取间隔长度)。但无论如何,您必须在CASE 子句中重新计算所有可能的区间类型

另一个好主意是 - 以统一的形式存储您的经期(例如,始终以天为单位) - 因此您将只为每一行存储一个数字(因此,1 周 = 7 天,等等)

【讨论】:

  • 这是完美的 - 但是,CHAR_LENGTH 需要为 +2 以说明字段值中的空间。我试图编辑答案,但它不会让我改变,因为它少于 6 个字符。
【解决方案2】:

您需要单独测试每个:

select product_name, start_date, expiry_period,
       (case when expiry_period like '%day'
             then DATE_ADD(start_date, INTERVAL expiry_period + 0 DAY) as end_date
             when expiry_period like '%week'
             then DATE_ADD(start_date, INTERVAL expiry_period + 0 WEEK) as end_date
             when expiry_period like '%month'
             then DATE_ADD(start_date, INTERVAL expiry_period + 0 MONTH) as end_date
             when expiry_period like '%year'
             then DATE_ADD(start_date, INTERVAL expiry_period + 0 YEAR) as end_date
       end)
from tbl_products;

算术(+ 0* 7)将字符串转换为数字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2021-09-06
    相关资源
    最近更新 更多