zoukankan      html  css  js  c++  java
  • SqlServer中 SET DATEFIRST更改

    在 SQL Server 中默认情况下,每周的开始都是从周日开始算起的,如果默认星期一呢?

    这里有三种方式可以解决这个问题:
    一:直接通过 SET DATEFIRST VALUE 来更改重新生成新的 DimDate,然后每次需要单独计算 Week Number 的时候根据 Date Key 关联一下就可以了,但这样就需要不断 JOIN DimDate,每一条记录都要 LookUp 一遍
    二:在存储过程中需要使用到  Week Number 的时候,就先设置一下 SET DATEFIRST 然后在使用 DATEPART() 函数来获取 Week Number
    SET DATEFIRST 1   --定义日期周一开始 
    

    三:直接写一个函数,每次调用一下就可以了

    SELECT @@DATEFIRST  --7
    SELECT DATENAME(WEEK,'2013-12-31') AS WeekName  -- 53
    SELECT DATENAME(WEEK,'2014-01-01') AS WeekName  -- 1
    SELECT DATENAME(WEEK,'2014-01-05') AS WeekName  -- 2
    

     代码:

    1.创建表:

    IF OBJECT_ID('DimDateStartWithMonday','U') IS NOT NULL
    DROP TABLE DimDateStartWithMonday
    GO
    
    CREATE TABLE DimDateStartWithMonday
    (
        DateKey INT PRIMARY KEY,
        FullDate DATE NOT NULL,
        [DateName] NVARCHAR(20),
        DayNumberOfWeek TINYINT NOT NULL,
        DayNameOfWeek NVARCHAR(10) NOT NULL,
        DayNumberOfMonth TINYINT NOT NULL,
        DayNumberOfYear SMALLINT NOT NULL, 
        WeekNumberOfYear TINYINT NOT NULL,
        EnglishMonthName NVARCHAR(10) NOT NULL,
        MonthNumberOfYear TINYINT NOT NULL,
        CalendarQuarter TINYINT NOT NULL,
        CalendarSemester TINYINT NOT NULL,
        CalendarYear SMALLINT NOT NULL 
    )
    

     2.插入值

    DECLARE @StartDate DATETIME
    DECLARE @EndDate DATETIME
    
    SELECT @StartDate = '2001-01-01',
           @EndDate = '2035-12-31'
    
    	   WHILE(@StartDate<+@EndDate)
    	   BEGIN
            INSERT INTO DimDateStartWithMonday 
        (
            DateKey,
            FullDate,
            [DateName],
            DayNumberOfWeek,
            DayNameOfWeek,
            DayNumberOfMonth,
            DayNumberOfYear, 
            WeekNumberOfYear,
            EnglishMonthName, 
            MonthNumberOfYear,
            CalendarQuarter,
            CalendarSemester,
            CalendarYear 
        )
        SELECT CAST(CONVERT(VARCHAR(8),@StartDate,112) AS INT) AS DateKey,
               CONVERT(VARCHAR(10), @StartDate,20) AS FullDate,
               CONVERT(VARCHAR(20), @StartDate,106) AS [DateName],
               DATEPART(DW,@StartDate) AS DayNumberOfWeek,
               DATENAME(DW,@StartDate) AS DayNameOfWeek,
               DATENAME(DD,@StartDate) AS [DayOfMonth],
               DATENAME(DY,@StartDate) AS [DayOfYear],  
               DATEPART(WW,@StartDate) AS WeekNumberOfYear,
               DATENAME(MM,@StartDate) AS EnglishMonthName,
               DATEPART(MM,@StartDate) AS MonthNumberOfYear,
               DATEPART(QQ,@StartDate) AS CalendarQuarter,
               CASE WHEN DATEPART(MM,@StartDate) BETWEEN 1 AND 6
                        THEN 1
                    ELSE 2
               END AS CalendarSemester,
               DATEPART(YY,@StartDate) AS CalendarYear 
    SET @StartDate = @StartDate + 1
    	   END
           
    

     3.自定义函数

    	   IF OBJECT_ID('ETLWORK_GETWEEKNUMBER','FN') IS NOT NULL
    DROP FUNCTION ETLWORK_GETWEEKNUMBER
    GO
     
    CREATE FUNCTION ETLWORK_GETWEEKNUMBER(@DATE DATETIME)  
    RETURNS INTEGER
    AS
    BEGIN 
     DECLARE @FIRST_DATE_OF_YEAR DATETIME = DATEADD(YYYY,DATEDIFF(YYYY,0,@DATE),0) 
    
      DECLARE @WEEK_NUMBER INTEGER
    
        -- 如果当前时间是当前年的第一天
        IF @DATE = @FIRST_DATE_OF_YEAR
            SET @WEEK_NUMBER = 1 
        -- 星期天是年第一天的情况
        ELSE IF (DATEPART(WEEKDAY,@DATE) = 1 AND DATEDIFF(DAYOFYEAR,@FIRST_DATE_OF_YEAR,@DATE)/7 + 1 = DATEPART(WEEK,@DATE))  
            SET @WEEK_NUMBER = DATEPART(WEEK,@DATE)  
        -- 星期天不是年第一天的情况
        ELSE IF (DATEPART(WEEKDAY,@DATE) = 1 AND DATEDIFF(DAYOFYEAR,@FIRST_DATE_OF_YEAR,@DATE)/7 + 1 <> DATEPART(WEEK,@DATE)) 
            SET @WEEK_NUMBER = DATEPART(WEEK,@DATE) - 1 
        -- 如果当前天的上一个周日小于年第一天
        ELSE IF DATEADD(DAY,-1,DATEADD(WK,DATEDIFF(WK,0,@DATE),0)) < @FIRST_DATE_OF_YEAR 
            SET @WEEK_NUMBER = 1 
        -- 当前天前面的一个周日正好是以周日为开始年的 7 倍的天数
        ELSE IF DATEDIFF(DAYOFYEAR,@FIRST_DATE_OF_YEAR,DATEADD(DAY,-1,DATEADD(WK,DATEDIFF(WK,0,@DATE),0) ))/7 + 1 = DATEPART(WEEK,@DATE) 
            SET @WEEK_NUMBER = DATEPART(WEEK,@DATE) + 1  
        ELSE 
            SET @WEEK_NUMBER = DATEPART(WEEK,@DATE)   
               
        RETURN @WEEK_NUMBER
    END
    

     测试:

    DECLARE @DATE DATETIME = '2017-01-02'
    DECLARE @FIRST_DATE_OF_YEAR DATETIME = DATEADD(YYYY,DATEDIFF(YYYY,0,@DATE),0) 
    
    SELECT DATEPART(WEEK,@DATE), -- 一年中的周数,默认以周日开始 
           DATEADD(WK,DATEDIFF(WK,0,@DATE),0), -- 当前周的周一,默认从周日开始,但是仍然找周一
           DATEADD(DAY,-1,DATEADD(WK,DATEDIFF(WK,0,@DATE),0)), -- 当前周先找周一,然后往前一天找到周日
           DATEDIFF(DAYOFYEAR,@FIRST_DATE_OF_YEAR,DATEADD(DAY,-1,DATEADD(WK,DATEDIFF(WK,0,@DATE),0))), -- 当前天离年第一天的间隔
           DATEDIFF(DAYOFYEAR,@FIRST_DATE_OF_YEAR,DATEADD(DAY,-1,DATEADD(WK,DATEDIFF(WK,0,@DATE),0) ))/7 + 1  -- 按天计算的周数
    
  • 相关阅读:
    Left Join
    SQL not exists双重否定
    修改页面下拉框的数据绑定为表里的数据
    myeclipse 项目运行时报错:运行项目时报错:Could not publish server configuration for Tomcat v6.0 Server at localhost. Multiple Contexts have a"/"
    关于js效果不提示就执行了刷新(解决 在hui框架中)
    使用 fn 标签 解决字数过多时用省略号代替 .............................
    java 优化
    java 使用substring 截取特殊字符串的后一位或者数字
    jsp页面 使用c 标签的 varStatus 属性和 index 解决一行显示多少个 然后进行自动换行
    jsp 页面通过jq处理默认 选中的项 数据是通过遍历显示
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/6879678.html
Copyright © 2011-2022 走看看