简体   繁体   中英

MariaDB start of week date & week number 1 to 52

I've written a stored procedure to get the week from a date, it also returns the date at the start of the week as well as the week number and year.

I'm aware of the 'WEEK' function, however this doesn't give me the date at the start of the week and I'm not aware of a function that does this given the week and year.

Question is:
How can I get the 'date' at the start of the week given the week number? Where the start of the week is passed in as a day index, 0 = Sunday, 1 = Monday etc.

My current function doesn't always work and if the first day of the week is Monday, then Sunday falls into the next week, not the end of the same week as I would like it to be.

I was digging around this for a bit too. But I stumbled on some mysql code that also worked. It basically subtracts days based on the day of the week. ie If the date is a Wed (4), you know the date was 1-4=-3 days ago.

How about this:

# 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

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

Use Sequence engine. You can adapt the following example as needed:

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)

Solved, I re-wrote the stored procedure:

    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

This routine does make use of other tables in my database and allows for companies to have different start of years.

As a test, I will find the start of the current week, first note:

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

Then this is the meat of the function:

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' is the beginning of the year in question.
24 is the WEEK() number.
+ 1 DAY is to compensate for start of week.
Something else needs to be done for handling your option of what day the week starts week.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM