【发布时间】:2008-12-08 07:55:34
【问题描述】:
是否可以创建一个选择周数(不是星期几 - 或一周中的天数)的 sql 语句。我正在创建一个视图来选择这个额外的信息以及其他几个字段,因此不能使用存储过程。我知道可以创建一个 UDF 来解决问题,但如果可能的话,我宁愿只向该数据库添加一个视图,而不是视图和函数。
有什么想法吗?我也是从哪里来的,一周从星期一开始,第一周是一年中的第一周,至少有 4 天。
相关:
【问题讨论】:
标签: sql-server tsql
是否可以创建一个选择周数(不是星期几 - 或一周中的天数)的 sql 语句。我正在创建一个视图来选择这个额外的信息以及其他几个字段,因此不能使用存储过程。我知道可以创建一个 UDF 来解决问题,但如果可能的话,我宁愿只向该数据库添加一个视图,而不是视图和函数。
有什么想法吗?我也是从哪里来的,一周从星期一开始,第一周是一年中的第一周,至少有 4 天。
【问题讨论】:
标签: sql-server tsql
请注意,正确的周数会有所不同,具体取决于文化。周数取决于几个不同国家/地区的假设,请参阅Wikipedia article on the matter。有一个适用于周数的ISO standard (ISO 8601)。
SQL 服务器集成DATEPART() 功能不一定做正确的事。 SQL Server 假设第 1 周的第 1 天是 1 月 1 日,对于许多应用程序来说这是错误的。
正确计算周数并非易事,在网上可以找到不同的实现。例如,有一个 UDF 可以计算 ISO week numbers from 1930-2030,这是众多其他函数之一。你必须检查什么对你有用。
这个来自Books Online(虽然你可能想用the one from Jonas Lincoln's answer,BOL版本好像不对):
CREATE FUNCTION ISOweek (@DATE DATETIME)
RETURNS INT
AS
BEGIN
DECLARE @ISOweek INT
SET @ISOweek = DATEPART(wk,@DATE)
+1
-DATEPART(wk,CAST(DATEPART(yy,@DATE) AS CHAR(4))+'0104')
-- Special cases: Jan 1-3 may belong to the previous year
IF (@ISOweek=0)
SET @ISOweek = dbo.ISOweek(CAST(DATEPART(yy,@DATE) - 1
AS CHAR(4))+'12'+ CAST(24+DATEPART(DAY,@DATE) AS CHAR(2)))+1
-- Special case: Dec 29-31 may belong to the next year
IF ((DATEPART(mm,@DATE)=12) AND
((DATEPART(dd,@DATE)-DATEPART(dw,@DATE))>= 28))
SET @ISOweek=1
RETURN(@ISOweek)
END
GO
【讨论】:
您需要 ISO 周。来自http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510,这是一个实现:
drop function dbo.F_ISO_WEEK_OF_YEAR
go
create function dbo.F_ISO_WEEK_OF_YEAR
(
@Date datetime
)
returns int
as
/*
Function F_ISO_WEEK_OF_YEAR returns the
ISO 8601 week of the year for the date passed.
*/
begin
declare @WeekOfYear int
select
-- Compute week of year as (days since start of year/7)+1
-- Division by 7 gives whole weeks since start of year.
-- Adding 1 starts week number at 1, instead of zero.
@WeekOfYear =
(datediff(dd,
-- Case finds start of year
case
when NextYrStart <= @date
then NextYrStart
when CurrYrStart <= @date
then CurrYrStart
else PriorYrStart
end,@date)/7)+1
from
(
select
-- First day of first week of prior year
PriorYrStart =
dateadd(dd,(datediff(dd,-53690,dateadd(yy,-1,aa.Jan4))/7)*7,-53690),
-- First day of first week of current year
CurrYrStart =
dateadd(dd,(datediff(dd,-53690,aa.Jan4)/7)*7,-53690),
-- First day of first week of next year
NextYrStart =
dateadd(dd,(datediff(dd,-53690,dateadd(yy,1,aa.Jan4))/7)*7,-53690)
from
(
select
--Find Jan 4 for the year of the input date
Jan4 =
dateadd(dd,3,dateadd(yy,datediff(yy,0,@date),0))
) aa
) a
return @WeekOfYear
end
go
【讨论】:
看起来DATEPART mssql function 应该可以帮助您解决...
DATEPART(wk, ‘Jan 1, xxxx’) = 1
好吧,我会的……原来有一种方法可以设置一周的第一天,DATEFIRST
SET DATEFIRST 1 -- for monday
更新:现在我更好地理解了 OP 想要什么......这是自定义逻辑。我不认为 MSSQL 会有如此丰富的自定义功能。但我可能错了......我认为你必须在这里推出自己的 UDF......对不起
【讨论】:
忘记其他答案
问题指定“一周从星期一开始,第 1 周是一年中的第一周,至少有 4 天。”这是 ISO 8601 标准,这个答案是什么提供。此功能在我们网站的生产环境中使用。
这就是你所需要的:
CREATE FUNCTION ISOweek (@DATE DATETIME)
RETURNS INT
AS
BEGIN
RETURN (datepart(DY, datediff(d, 0, @DATE) / 7 * 7 + 3)+6) / 7
END
GO
【讨论】:
这将返回您在引号中输入的日期的周数
SELECT DATEPART( wk, 'enter the date over here' )
【讨论】:
看起来 datepart 可以帮助您完成部分任务,但您必须根据给定年份 1 月 1 日的星期几进行调整才能获得正确的周数。我对 T-SQL 不够熟悉,无法做到这一点,但应该可以。可惜没有MySQL中的模式参数
【讨论】:
您是否考虑过使用 WEEK 功能?
这将为您提供指定日期的一年中的哪一周。
SELECT { fn WEEK(GETDATE()) } AS WeekNumber, { fn WEEK(CONVERT(DATETIME, '2008-01-01 00:00:00', 102)) } AS FirstWeekOfYear, { fn WEEK(CONVERT(DATETIME, '2008-12-31 00:00:00', 102)) } AS LastWeekOfYear
这会输出以下 SQL2000 和 SQL2005:
我希望这会有所帮助:)
【讨论】:
为什么又一次,人们用鼹鼠山造山,这让我很吃惊?
这么简单……
select DATEPART(wk, GETDATE())
【讨论】: