SQL Server,尝试通过确定性UDF获取星期几。

我确信这一定是可能的,但无法弄明白。

更新:示例代码..

CREATE VIEW V_Stuff WITH SCHEMABINDING AS 
SELECT    
MD.ID, 
MD.[DateTime]
...
        dbo.FN_DayNumeric_DateTime(MD.DateTime) AS [Day], 
        dbo.FN_TimeNumeric_DateTime(MD.DateTime) AS [Time], 
...
FROM       {SOMEWHERE}
GO
CREATE UNIQUE CLUSTERED INDEX V_Stuff_Index ON V_Stuff (ID, [DateTime])
GO
有帮助吗?

解决方案

好的,我认为..

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

其他提示

与上述解决方案略有相似的方法,但只是一个可以在函数内部使用的单行程序或计算列的内联。

假设:

  1. 您之前没有日期 1899-12-31(周日)
  2. 你想模仿@@ datefirst = 7
  3. @dt是smalldatetime,datetime, date或datetime2数据类型
  4. 如果您想要与众不同,请将日期'18991231'更改为您希望等于1的工作日的日期.convert()函数是使整个工作正常工作的关键 - 强制转换不是诀窍:

      

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

取自确定性标量函数获得一年中某一周的日期

;
with 
Dates(DateValue) as 
(
    select cast('2000-01-01' as date)
    union all 
    select dateadd(day, 1, DateValue) from Dates where DateValue < '2050-01-01'
)
select 
    year(DateValue) * 10000 + month(DateValue) * 100 + day(DateValue) as DateKey, DateValue,        
    datediff(day, dateadd(week, datediff(week, 0, DateValue), 0), DateValue) + 2 as DayOfWeek,
    datediff(week, dateadd(month, datediff(month, 0, DateValue), 0), DateValue) + 1 as WeekOfMonth,
    datediff(week, dateadd(year, datediff(year, 0, DateValue), 0), DateValue) + 1 as WeekOfYear
    from Dates option (maxrecursion 0)

我知道这篇文章已经超级老了,但是我试图做一个类似的事情,并提出了一个不同的解决方案,并认为我会发布后代。另外,我做了一些搜索,并没有找到关于这个问题的更多内容。

就我而言,我试图使用计算列PERSISTED,这要求计算是确定性的。我使用的计算是:

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

我们的想法是找出一个已知的星期日,你知道会在你的表格中任何可能的日期之前发生(在这种情况下,2010年1月3日),然后计算自该星期日以来天数的模数7 + 1。

问题是在函数调用中包含一个文字日期足以将其标记为非确定性。您可以通过使用整数0来表示时间段来解决这个问题,对于SQL Server,它是1900年1月1日的星期日。

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

当datefirst设置为7(默认为美国)时,+1只会使结果与datepart(dw,[datecolumn])相同,它将星期日设置为1,将星期一设置为2,等等

我也可以结合案例[thatComputedColumn]当1然后'星期日'时2然后'星期一'......等等,但是确定性的,这是我周围的要求。

在sql中有一个已经内置的函数来执行它:

SELECT DATEPART(weekday, '2009-11-11')

修改: 如果你真的需要确定性UDF:

CREATE FUNCTION DayOfWeek(@myDate DATETIME ) 
RETURNS int
AS
BEGIN
RETURN DATEPART(weekday, @myDate)
END
GO
SELECT dbo.DayOfWeek('2009-11-11')

再次编辑:这实际上是错误的,因为 DATEPART(工作日)不是确定性的。

<强>更新 DATEPART(工作日)是非确定性的,因为它依赖于 DATEFIRST source )。
您可以使用 SET DATEFIRST 更改它,但不能在存储的函数内调用它。

我认为下一步是使用您首选的DATEFIRST 制作您自己的实施它(并没有考虑它,例如使用 Monday 作为第一天)。

建议的解决方案有一个问题 - 它在周六返回0。假设我们正在寻找与 DATEPART(WEEKDAY)兼容的东西,这是一个问题。

但是,没有什么简单的 CASE 语句不会修复。

创建一个函数,并将@dbdate varchar(8)作为输入变量。

让它返回以下内容:

RETURN (DATEDIFF(dd, -1, convert(datetime, @dbdate, 112)) % 7)+1;

值112是sql样式YYYYMMDD。

这是确定性的,因为datediff没有收到字符串输入,如果它要接收一个它不再有效的字符串,因为它在内部将它转换为datetime对象。这不是确定性的。

不确定您要找的是什么,但如果这是网站的一部分,请从 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;
}

星期几?你为什么不只使用DATEPART?

DATEPART(weekday, YEAR_DATE)

你不能只用以下的东西选择它:

SELECT DATENAME(dw, GETDATE());
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top