【问题标题】:MariaDB start of week date & week number 1 to 52MariaDB 开始日期和第 1 到第 52 周
【发布时间】:2016-10-07 20:18:50
【问题描述】:

我编写了一个存储过程来从日期获取星期,它还返回星期开始时的日期以及星期数和年份。

我知道“WEEK”功能,但是这并没有给我一周开始的日期,而且我不知道在给定周和年的情况下执行此操作的功能。

问题是:
给定周数,如何在一周开始时获得“日期”?一周的开始作为日期索引传入,0 = 星期日,1 = 星期一等。

我当前的功能并不总是有效,如果一周的第一天是星期一,那么星期天就会进入下周,而不是我希望的同一周的结束。

【问题讨论】:

  • 谁能帮忙解决这个问题?

标签: sql stored-procedures mariadb


【解决方案1】:

我也在研究这个问题。但我偶然发现了一些也有效的 mysql 代码。它基本上是根据星期几减去天数。即,如果日期是星期三 (4),您知道日期是 1-4=-3 天前。

这个怎么样:

# with Sunday being the start of the week:
select convert(date_add(now(), interval(1-dayofweek(now())) day), date) as WeekStartDate
select convert(date_add(now(), interval(7-dayofweek(now())) day), date) as WeekEndDate

# with Monday being the start of the week:
select convert(date_add(now(), interval(2-dayofweek(now())) day), date) as WeekStartDate
select convert(date_add(now(), interval(8-dayofweek(now())) day), date) as WeekEndDate

信用: How do I get the first day of the week of a date in mysql?

【讨论】:

    【解决方案2】:

    使用Sequence 引擎。您可以根据需要修改以下示例:

    MariaDB [_]> SHOW ENGINES\G
    .
    .
    .
    *************************** 3. row ***************************
          Engine: SEQUENCE
         Support: YES
         Comment: Generated tables filled with sequential values
    Transactions: YES
              XA: NO
      Savepoints: YES
    .
    .
    .
    
    MariaDB [_]> SET @`year` := 2016,
              ->     @`mode` := 1,
              ->     @`week` := 23;
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [_]> SELECT
              ->   `der`.`date`,
              ->   `der`.`week`,
              ->   `der`.`year`
              -> FROM (
              ->   SELECT
              ->     `der`.`date`,
              ->     WEEK(`der`.`date`, @`mode`) `week`,
              ->     YEAR(`der`.`date`) `year`
              ->   FROM (
              ->     SELECT
              ->       DATE_ADD(CONCAT(@`year`, '-01-01'), INTERVAL `s`.`seq` DAY) `date`
              ->     FROM
              ->       seq_0_to_365 `s`
              ->   ) `der`
              -> ) `der`
              -> WHERE
              ->   `der`.`week` = @`week` AND
              ->   `der`.`year` = @`year`;
    +------------+------+------+
    | date       | week | year |
    +------------+------+------+
    | 2016-06-06 |   23 | 2016 |
    | 2016-06-07 |   23 | 2016 |
    | 2016-06-08 |   23 | 2016 |
    | 2016-06-09 |   23 | 2016 |
    | 2016-06-10 |   23 | 2016 |
    | 2016-06-11 |   23 | 2016 |
    | 2016-06-12 |   23 | 2016 |
    +------------+------+------+
    7 rows in set (0.01 sec)
    

    【讨论】:

    • 我怀疑这种使用sequence的方式会导致计算全年的数据,只返回一天的结果?
    • @RickJames:没错,这是解决方案选项的缺点。
    【解决方案3】:

    解决了,我重写了存储过程:

        exitProc:BEGIN
        #--
        # Procedure:
        #   weekFromDate
        #
        # Parameters:
        #   vcCompKey, the key associated with the company
        #   dtDate, the date to translate
        #   dtOutSOW, returned start of week date
        #   siOutWeek, returned week number
        #   siOutYear, returned year
        #--
            DECLARE siDIY          SMALLINT;   #Day in year
            DECLARE siFDOW         SMALLINT;   #First day of week
            DECLARE siGoBack       SMALLINT;      #Flag used to check for last year
            DECLARE siRmonth       SMALLINT;   #Reference Month
            DECLARE siRyear        SMALLINT;   #Reference Year
            DECLARE dtSOY          DATE;       #Date of start of year
            DECLARE vcFMDOY        VARCHAR(12);#First month and day of year
            DECLARE vcFDOW         VARCHAR(12);#First day of the week
            DECLARE vcDYSOW        VARCHAR(80);#Days of week
        #Get the first day of the week for the specified company
            SET vcFDOW = vcGetParamValue(vcCompKey, 'Var:First day of week');
    
        IF (vcFDOW IS NULL) THEN
        #No entry found, abort! 
            LEAVE exitProc;
        END IF;
        #Get the first month and day of the year for the specified company
        SET vcFMDOY = vcGetParamValue(vcCompKey, 'Var:First day of year');  
    
        IF (vcFMDOY IS NULL) THEN
        #No entry found, abort! 
            LEAVE exitProc;
        END IF;
        #Set-up days of week
        SET vcDYSOW = 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday';   
        #Get the first day of the week index base 1
        SET siFDOW = FIND_IN_SET(LOWER(vcFDOW), LOWER(vcDYSOW)) - 1;
        #Get the reference month and year   
        SET siRmonth = MONTH(dtDate);
        SET siRyear = YEAR(dtDate);
        SET dtSOY = DATE(CONCAT(siRyear, '/', vcFMDOY)); 
        #Calculate the start of week date
        SET dtOutSOW = DATE_SUB(dtDate, INTERVAL (DAYOFWEEK(dtDate) - siFDOW) DAY) + 1;
        #Calculate the day in year
        SET siDIY = DATEDIFF(dtOutSOW, dtSOY);
        #Do we need to go back to the end of the previous year? 
        SET siGoBack = YEAR(dtDate) - YEAR(dtOutSOW);
    
        IF siGoBack < 0 Or siDIY < 0 Or dtDate < dtOutSOW THEN
        #Yes
            IF YEAR(dtOutSOW) = YEAR(dtDate) THEN
                SET dtOutSOW = DATE_SUB(dtOutSOW, INTERVAL 7 DAY);
            END IF;
            SET dtSOY = DATE(CONCAT(YEAR(dtOutSOW), '/', vcFMDOY)); 
            SET siDIY = DATEDIFF(dtOutSOW, dtSOY);
        END IF;     
        #Calculate the week no. and year
        SET siOutWeek = (siDIY / 7) + 1;
        SET siOutYear = YEAR(dtOutSOW); 
    END
    

    这个例程确实利用了我数据库中的其他表,并允许公司有不同的年份开始。

    【讨论】:

      【解决方案4】:

      作为测试,我会找到本周的开始,第一个注释:

      mysql> SELECT NOW(), WEEK(NOW());
      +---------------------+-------------+
      | NOW()               | WEEK(NOW()) |
      +---------------------+-------------+
      | 2016-06-18 12:10:58 |          24 |
      +---------------------+-------------+
      

      那么这就是函数的核心:

      mysql> SELECT '2016-01-01'
                   + INTERVAL 7*24
                   - DAYOFWEEK('2016-01-01')
                   + 1 DAY;
      +----------------------------------------------------------------+
      | '2016-01-01' + INTERVAL 7*24 - DAYOFWEEK('2016-01-01') + 1 DAY |
      +----------------------------------------------------------------+
      | 2016-06-12                                                     |
      +----------------------------------------------------------------+
      

      '2016-01-01' 是相关年份的开始。
      24WEEK() 数字。
      + 1 DAY 是为了补偿一周的开始。
      需要做一些其他事情来处理您选择一周从哪一天开始的选项。

      【讨论】:

        【解决方案5】:

        对 user1014010 的回答进行了一些更正。当一周从星期一开始时,您将收到下周的星期日日期。这是我的更正:

        SELECT DATE(DATE_ADD(NOW(), INTERVAL -((5 + DAYOFWEEK(NOW())) % 7) DAY)) AS WeekStartDate
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-21
          • 2018-07-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多