Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在MySQL中更改日期时间值_Mysql_Sql_Datetime - Fatal编程技术网

在MySQL中更改日期时间值

在MySQL中更改日期时间值,mysql,sql,datetime,Mysql,Sql,Datetime,我想做的是设置时间间隔的开始,若并没有正确地设置到存储过程中。然而,不知何故,它并没有起到很好的作用 这是我的代码: CREATE PROCEDURE intervals_generator (IN start DATETIME, IN ending DATETIME, IN intervalis INT) BEGIN -- temp values DECLARE next_date DATETIME; -- result temp values DECLAR

我想做的是设置时间间隔的开始,若并没有正确地设置到存储过程中。然而,不知何故,它并没有起到很好的作用

这是我的代码:

CREATE PROCEDURE intervals_generator (IN start DATETIME, IN ending DATETIME, IN intervalis INT)
BEGIN

    -- temp values
    DECLARE next_date DATETIME;

    -- result temp values
    DECLARE start_temp DATETIME;
    DECLARE ending_temp DATETIME;

    -- date formatting variables
    DECLARE year CHAR(20);
    DECLARE month CHAR(20);
    DECLARE day CHAR(20);

    DECLARE new_start CHAR(20);

    -- SET starting date if is incorrect  DATE_FORMAT(NOW(), '%d %m %Y')
    SET year := DATE_FORMAT(start, '%Y');
    SET month := DATE_FORMAT(start, '%c');
    SET day := DATE_FORMAT(start, '%e');

    IF intervalis = '1_day' THEN
        BEGIN
            SET new_start := year+' '+month+' '+day+' 00:00:00';
        END;
    ELSEIF intervalis = '1_month' THEN
        BEGIN
            SET new_start := year+' '+month+' 1 00:00:00';
        END;
    ELSEIF intervalis = '1_quarter' THEN
        BEGIN
            IF MONTH(start) IN (2, 3) THEN
                SET month := 1;
            ELSEIF MONTH(start) IN (5, 6) THEN
                SET month := 4;
            ELSEIF MONTH(start) IN (8, 9) THEN
                SET month := 7;
            ELSEIF MONTH(start) IN (11, 12) THEN
                SET month := 10;
            END IF;
            SET new_start := year+' '+month+' 1 00:00:00';
        END;
    ELSEIF intervalis = '1_year' THEN
        BEGIN
            SET new_start := year+' 1 1 00:00:00';
        END;
    END IF;
    SET start := STR_TO_DATE(new_start, '%Y %c %e %h:%i:%s');

    SELECT year, month, day, start;
    DROP TEMPORARY TABLE IF EXISTS intervals_result;

END//

DELIMITER ;
我尝试了许多不同的格式化设置和函数,但输出仍然错误,如下所示:

mysql> CALL intervals_generator('2013-02-01 00:00:00', '2015-12-31 00:00:00', '1_year');
+------+-------+------+---------------------+
| year | month | day  | start               |
+------+-------+------+---------------------+
| 2013 | 2     | 1    | 2016-00-00 00:00:00 |
+------+-------+------+---------------------+
1 row in set (0.02 sec)

Query OK, 0 rows affected, 1 warning (0.02 sec)
我真不明白为什么输出是“2016-00-00”而不是“2013-01-01”。年、月和日变量定义为CHAR,从datetime提取它们的函数也应该返回CHAR。函数STR_TO_DATE也应该采用CHAR格式,所以对我来说这是个谜

如果有人有什么想法,请给我一个提示。

如果你在中而不是字符串中工作,你可以利用MySQL的日期,让一切变得更简单。。。但不要太简单,因为这是MySQL

MySQL和dates的问题在于它的日期功能是一个真正的mish mash,有时使用
date
s,有时使用字符串,有时使用整数,并且缺少基本功能。它缺少一个简单的函数来设置日期;没有将
日期的
月份
部分更改为2月份的功能。甚至没有一个很好的方法可以根据年、月、日来确定日期,你得到的最接近的东西是哪一年、哪一天(?)。这总比摆弄琴弦好

例如,如果您有
2013-02-12
并且想要
2013-02-01
您必须首先使用年份创建一个新日期,然后添加月份部分

-- 2013-01-01
SET new_date := MAKEDATE(YEAR(old_date), 1);

-- 2013-02-01
-- Since MONTH returns from 1 to 12, you need to take away one.
SET new_date := new_date + (INTERVAL MONTH(old_date) - 1) MONTH;
剔除所有未使用的变量,更改为最新数学,并使用而不是大的IF/ELSE链,我们得到以下结果:

CREATE PROCEDURE intervals_generator (IN start_date DATE, IN intervals TEXT)
BEGIN
    DECLARE new_start DATE;

    CASE intervals
        WHEN '1_day' THEN
            -- Nothing to do, DATE has already truncated the time portion.
            SET new_start := start_date;
        WHEN '1_month' THEN
            -- Set to the year and month of the start date
            SET new_start := MAKEDATE(YEAR(start_date), 1) + INTERVAL (MONTH(start_date) - 1) MONTH;
        WHEN '1_quarter' THEN
        BEGIN
            -- Set to the year and month of the start date
            SET new_start := MAKEDATE(YEAR(start_date), 1) + INTERVAL (MONTH(start_date) - 1) MONTH;
            -- Subtract the necessary months for the beginning of the quarter
            SET new_start := new_start - INTERVAL (MONTH(new_start) - 1) % 3 MONTH;
        END;
        WHEN '1_year' THEN
            -- Set the date to the first day of the year
            SET new_start := MAKEDATE(YEAR(start_date), 1);
    END CASE;

    SELECT new_start;
END//

这句话没有达到你的预期:

SET new_start := year+' '+month+' '+day+' 00:00:00';
在MySQL中,
+
操作符执行加法。就是这样,不是串联

我认为你打算:

SET new_start := concat(year, ' ', month, ' ', day, ' 00:00:00');

我还没有研究其余的逻辑,看它是否有意义,但这是一个突出的问题。

您可以使用内置的,而不是从容易出错的部分(串联)切片和构建新的日期:

SET @date = '2013-05-03 10:05:00';
SELECT CAST(@date AS DATETIME) AS Date,
   DATE_FORMAT(@date ,'%Y-01-01 00:00:00') AS Year_Allign,
   CASE EXTRACT(QUARTER FROM @date)
      WHEN 1 THEN DATE_FORMAT(@date ,'%Y-01-01 00:00:00')
      WHEN 2 THEN DATE_FORMAT(@date ,'%Y-04-01 00:00:00')
      WHEN 3 THEN DATE_FORMAT(@date ,'%Y-07-01 00:00:00')
      WHEN 4 THEN DATE_FORMAT(@date ,'%Y-10-01 00:00:00')
      ELSE NULL END AS Quarter_Allign,
   DATE_FORMAT(@date ,'%Y-%m-01 00:00:00') AS Month_Allign,
   DATE_FORMAT(@date ,'%Y-%m-%d 00:00:00') AS Day_Allign;  
SET @date = '2013-05-03 10:05:00';
SET @allign = '1_QUARTER';
SELECT
   CAST(@date AS DATETIME) AS Date,
   CASE @allign
     WHEN '1_YEAR' THEN  DATE_FORMAT(@date ,'%Y-01-01 00:00:00')
     WHEN '1_QUARTER' THEN  (CASE EXTRACT(QUARTER FROM @date)
                              WHEN 1 THEN DATE_FORMAT(@date ,'%Y-01-01 00:00:00')
                              WHEN 2 THEN DATE_FORMAT(@date ,'%Y-04-01 00:00:00')
                              WHEN 3 THEN DATE_FORMAT(@date ,'%Y-07-01 00:00:00')
                              WHEN 4 THEN DATE_FORMAT(@date ,'%Y-10-01 00:00:00')
                              ELSE NULL END)
     WHEN '1_MONTH' THEN DATE_FORMAT(@date ,'%Y-%m-01 00:00:00')
     WHEN '1_DAY' THEN  DATE_FORMAT(@date ,'%Y-%m-%d 00:00:00')
     ELSE NULL
     END AS Alligned;

SET @date = '2013-05-03 10:05:00';
SELECT CAST(@date AS DATETIME) AS Date,
   DATE_FORMAT(@date ,'%Y-01-01 00:00:00') AS Year_Allign,
   CASE EXTRACT(QUARTER FROM @date)
      WHEN 1 THEN DATE_FORMAT(@date ,'%Y-01-01 00:00:00')
      WHEN 2 THEN DATE_FORMAT(@date ,'%Y-04-01 00:00:00')
      WHEN 3 THEN DATE_FORMAT(@date ,'%Y-07-01 00:00:00')
      WHEN 4 THEN DATE_FORMAT(@date ,'%Y-10-01 00:00:00')
      ELSE NULL END AS Quarter_Allign,
   DATE_FORMAT(@date ,'%Y-%m-01 00:00:00') AS Month_Allign,
   DATE_FORMAT(@date ,'%Y-%m-%d 00:00:00') AS Day_Allign;  
SET @date = '2013-05-03 10:05:00';
SET @allign = '1_QUARTER';
SELECT
   CAST(@date AS DATETIME) AS Date,
   CASE @allign
     WHEN '1_YEAR' THEN  DATE_FORMAT(@date ,'%Y-01-01 00:00:00')
     WHEN '1_QUARTER' THEN  (CASE EXTRACT(QUARTER FROM @date)
                              WHEN 1 THEN DATE_FORMAT(@date ,'%Y-01-01 00:00:00')
                              WHEN 2 THEN DATE_FORMAT(@date ,'%Y-04-01 00:00:00')
                              WHEN 3 THEN DATE_FORMAT(@date ,'%Y-07-01 00:00:00')
                              WHEN 4 THEN DATE_FORMAT(@date ,'%Y-10-01 00:00:00')
                              ELSE NULL END)
     WHEN '1_MONTH' THEN DATE_FORMAT(@date ,'%Y-%m-01 00:00:00')
     WHEN '1_DAY' THEN  DATE_FORMAT(@date ,'%Y-%m-%d 00:00:00')
     ELSE NULL
     END AS Alligned;

函数应返回时间间隔,4种可能:天、月、季度、年。在程序的第一部分(我在这个问题中讨论的),它应该找到第一时间间隔。因此,例如,如果我选择季度间隔,并将开始日期时间输入为“2013-05-03”,则此代码应将我的输入更正为“2013-04-01”,因为这是第二季度的真正开始,我给定的开始日期适用于该季度。如果我选择了年间隔,我的函数应该将我的输入日期更改为给定年份的第一个一月,如果我的输入日期不是第一个一月。你不能使用更简单的方法,比如或@lad2025,这将是很好的答案。暗示hint@Schwern作为答案发布供将来参考:)谢谢你告诉我问题出在哪里。我已经习惯了postgreSQL,这是我必须在MySQL中完成的一个项目,所以这对我来说是很大的帮助。:)