Deterministic scalar function to get day of week for a date

后端 未结 11 1533
孤街浪徒
孤街浪徒 2021-01-13 00:10

SQL Server, trying to get day of week via a deterministic UDF.

Im sure this must be possible, but cant figure it out.

UPDATE: SAMPLE CODE..

C         


        
相关标签:
11条回答
  • 2021-01-13 00:36

    Slightly similar approach to aforementioned solution, but just a one-liner that could be used inside a function or inline for computed column.

    Assumptions:

    1. You don't have dates before 1899-12-31 (which is a Sunday)
    2. You want to imitate @@datefirst = 7
    3. @dt is smalldatetime, datetime, date, or datetime2 data type

    If you'd rather it be different, change the date '18991231' to a date with the weekday that you'd like to equal 1. The convert() function is key to making the whole thing work - cast does NOT do the trick:

    ((datediff(day, convert(datetime, '18991231', 112), @dt) % 7) + 1)

    0 讨论(0)
  • 2021-01-13 00:36

    I know this post is way-super-old, but I was trying to do a similar thing and came up with a different solution and figured I'd post for posterity. Plus I did some searching around and did not find much content on this question.

    In my case, I was trying to use a computed column PERSISTED, which requires the calculation to be deterministic. The calculation I used is:

    datediff(dd,'2010-01-03',[DateColumn]) % 7 + 1
    

    The idea is to figure out a known Sunday that you know will occur before any possible date in your table (in this case, Jan 3 2010), then calculate the modulo 7 + 1 of the number of days since that Sunday.

    The problem is that including a literal date in the function call is enough to mark it as non-deterministic. You can work around that by using the integer 0 to represent the epoch, which for SQL Server is Jan 1st, 1900, a Sunday.

    datediff(dd,0,[DateColumn]) % 7 + 1
    

    The +1 just makes the result work the same as datepart(dw,[datecolumn]) when datefirst is set to 7 (default for US), which sets Sunday to 1, Monday to 2, etc

    I can also use this in conjunction with case [thatComputedColumn] when 1 then 'Sunday' when 2 then 'Monday' ... etc. Wordier, but deterministic, which was a requirement in my environs.

    0 讨论(0)
  • 2021-01-13 00:42

    Ok, i figured it..

    CREATE FUNCTION [dbo].[FN_DayNumeric_DateTime] 
    (@DT DateTime)
    RETURNS INT WITH SCHEMABINDING
    AS 
    BEGIN
    DECLARE @Result int 
    DECLARE  @FIRST_DATE        DATETIME
    SELECT @FIRST_DATE = convert(DATETIME,-53690+((7+5)%7),112)
    SET  @Result = datediff(dd,dateadd(dd,(datediff(dd,@FIRST_DATE,@DT)/7)*7,@FIRST_DATE), @DT)
    RETURN (@Result)
    END
    GO
    
    0 讨论(0)
  • 2021-01-13 00:42

    Not sure what you are looking for, but if this is part of a website, try this php function from http://php.net/manual/en/function.date.php

    function weekday($fyear, $fmonth, $fday) //0 is monday
    {
      return (((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, 7, 17,   2006))/(60*60*24))+700000) % 7;
    }
    
    0 讨论(0)
  • 2021-01-13 00:44

    Although this is old. Commenting simple answer to help future readers. @liver-larson was almost correct. Made a wrong assumption of epoch time 0 (Jan 1st, 1900) being a Sunday. It is actually a Monday.

    Wrong code - https://stackoverflow.com/a/20481717/2012977

    datediff(dd,0,[DateColumn]) % 7 + 1
    

    Correction

    datediff(dd,-1,[DateColumn]) % 7 + 1
    

    I like this answer because there is no date conversion happening and guaranteed deterministic.

    Unit test of code. Sadly SqlFiddle down at the moment of writing. Note hardcoding column value here. Expect column to be a date type.

    SELECT DATEPART(WEEKDAY, '2020-06-14'), DATEDIFF(dd, -1, '2020-06-14') % 7 + 1
    SELECT DATEPART(WEEKDAY, '2020-06-15'), DATEDIFF(dd, -1, '2020-06-15') % 7 + 1
    SELECT DATEPART(WEEKDAY, '2020-06-16'), DATEDIFF(dd, -1, '2020-06-16') % 7 + 1
    SELECT DATEPART(WEEKDAY, '2020-06-17'), DATEDIFF(dd, -1, '2020-06-17') % 7 + 1
    SELECT DATEPART(WEEKDAY, '2020-06-18'), DATEDIFF(dd, -1, '2020-06-18') % 7 + 1
    SELECT DATEPART(WEEKDAY, '2020-06-19'), DATEDIFF(dd, -1, '2020-06-19') % 7 + 1
    SELECT DATEPART(WEEKDAY, '2020-06-20'), DATEDIFF(dd, -1, '2020-06-20') % 7 + 1
    
    0 讨论(0)
提交回复
热议问题