我遇到了如何根据包含日期的列创建计算列的问题。例如,我有一个包含从7月开始的日期的列。
需要按照使用SQL服务器的图片中所述计算DAY。
那么基本上可以根据包含大量日期的现有列创建列吗?我需要这是动态的。
WeekDay Date Day
---------------------------
Friday 3-Jan-14 1
Monday 6-Jan-14 2
Tuesday 7-Jan-14 3
Wednesday 8-Jan-14 4
Thursday 9-Jan-14 5
Friday 10-Jan-14 6
Monday 13-Jan-14 7
Tuesday 14-Jan-14 8
Wednesday 15-Jan-14 9
Thursday 16-Jan-14 10
Friday 17-Jan-14 11
Monday 20-Jan-14 12
Tuesday 21-Jan-14 13
Wednesday 22-Jan-14 14
Thursday 23-Jan-14 15
Friday 24-Jan-14 16
Monday 27-Jan-14 17
Tuesday 28-Jan-14 18
Wednesday 29-Jan-14 19
Thursday 30-Jan-14 20
Friday 31-Jan-14 21
答案 0 :(得分:3)
对于表,DateTable,其列为Date类型Date,以下查询将按您的要求执行。
SELECT
DATENAME(dw, Date) AS WeekDay
,Date
,ROW_NUMBER() OVER (ORDER BY Date) AS Day
FROM DateTable
WHERE DATEPART(dw, Date) NOT IN (1, 7)
ORDER BY Date
答案 1 :(得分:0)
根据标题和主题,我猜您想尝试识别每个月的工作日数。
示例:
1月1日 - 14日是星期三,因此其工作日数为1
6月1日至14日是星期一,所以4号工作日(4月1日至14日和5月1日至14日是周末)
此外,结果应该是已有数据的表中的派生列。
如果以上情况属实,那么这就是我的建议
示例查询:
IF OBJECT_ID('test') > 0
BEGIN
DROP TABLE test
END;
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufn_WordkindDayNumber]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].ufn_WordkindDayNumber
GO
CREATE FUNCTION ufn_WordkindDayNumber(@Date DATETIME)
RETURNS INT
AS
BEGIN
DECLARE @LastDayofPreviousMonth DATETIME,
@Return int
SET @LastDayofPreviousMonth = CAST(YEAR(@Date) as VARCHAR(4))+RIGHT('00'+CAST(MONTH(@Date) as VARCHAR(2)),2)+'01'
SET @LastDayofPreviousMonth = DATEADD (day, -1, CAST(@LastDayofPreviousMonth AS DATE))
-- Logic addapted from http://stackoverflow.com/questions/252519/count-work-days-between-two-dates. Credit CMS
SELECT @Return =
CASE
WHEN DATENAME(dw, @Date) = 'Sunday' OR DATENAME(dw, @Date) = 'Saturday' THEN 0
ELSE
(DATEDIFF(dd, @LastDayofPreviousMonth, @Date))
-(DATEDIFF(wk, @LastDayofPreviousMonth, @Date) * 2)
-(CASE WHEN DATENAME(dw, @Date) IN ('Saturday', 'Sunday') THEN 1 ELSE 0 END)
END
-- Return the result of the function
RETURN @Return
END
GO
CREATE TABLE test ([date] DATE NULL);
INSERT INTO test
SELECT '27-Dec-13' UNION ALL
SELECT '28-Dec-13' UNION ALL
SELECT '29-Dec-13'
ALTER TABLE test
ADD WordkindDayNumber AS dbo.ufn_WordkindDayNumber(Date);
GO
INSERT INTO test
SELECT '30-Dec-13' UNION ALL
SELECT '31-Dec-13'
SELECT *
FROM test;
DROP TABLE test;
验证脚本:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufn_WordkindDayNumber]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].ufn_WordkindDayNumber
GO
CREATE FUNCTION ufn_WordkindDayNumber(@Date DATETIME)
RETURNS INT
AS
BEGIN
DECLARE @LastDayofPreviousMonth DATETIME,
@Return int
SET @LastDayofPreviousMonth = CAST(YEAR(@Date) as VARCHAR(4))+RIGHT('00'+CAST(MONTH(@Date) as VARCHAR(2)),2)+'01'
SET @LastDayofPreviousMonth = DATEADD (day, -1, CAST(@LastDayofPreviousMonth AS DATE))
-- Logic addapted from http://stackoverflow.com/questions/252519/count-work-days-between-two-dates. Credit CMS
SELECT @Return =
CASE
WHEN DATENAME(dw, @Date) = 'Sunday' OR DATENAME(dw, @Date) = 'Saturday' THEN 0
ELSE
(DATEDIFF(dd, @LastDayofPreviousMonth, @Date))
-(DATEDIFF(wk, @LastDayofPreviousMonth, @Date) * 2)
-(CASE WHEN DATENAME(dw, @Date) IN ('Saturday', 'Sunday') THEN 1 ELSE 0 END)
END
-- Return the result of the function
RETURN @Return
END
GO
;WITH cte_TestData(Date) AS
(SELECT '30-Dec-13' UNION ALL
SELECT '31-Dec-13' UNION ALL
SELECT '1-Jan-14' UNION ALL
SELECT '2-Jan-14' UNION ALL
SELECT '3-Jan-14' UNION ALL
SELECT '4-Jan-14' UNION ALL
SELECT '5-Jan-14' UNION ALL
SELECT '6-Jan-14' UNION ALL
SELECT '7-Jan-14' UNION ALL
SELECT '8-Jan-14' UNION ALL
SELECT '9-Jan-14' UNION ALL
SELECT '10-Jan-14' UNION ALL
SELECT '11-Jan-14' UNION ALL
SELECT '12-Jan-14' UNION ALL
SELECT '13-Jan-14' UNION ALL
SELECT '14-Jan-14' UNION ALL
SELECT '15-Jan-14' UNION ALL
SELECT '16-Jan-14' UNION ALL
SELECT '17-Jan-14' UNION ALL
SELECT '18-Jan-14' UNION ALL
SELECT '19-Jan-14' UNION ALL
SELECT '20-Jan-14' UNION ALL
SELECT '21-Jan-14' UNION ALL
SELECT '22-Jan-14' UNION ALL
SELECT '23-Jan-14' UNION ALL
SELECT '24-Jan-14' UNION ALL
SELECT '25-Jan-14' UNION ALL
SELECT '26-Jan-14' UNION ALL
SELECT '27-Jan-14' UNION ALL
SELECT '28-Jan-14' UNION ALL
SELECT '29-Jan-14' UNION ALL
SELECT '30-Jan-14' UNION ALL
SELECT '31-Jan-14' )
,cte_FirstDateofMonth as
(
SELECT Date,
CAST(YEAR(DATE) as VARCHAR(4))+RIGHT('00'+CAST(MONTH(DATE) as VARCHAR(2)),2)+'01' AS FDoM
FROM cte_TestData
)
,cte_LastDayofPreviousMonth as
(
SELECT Date,
DATEADD (day, -1, CAST(FDoM AS DATE)) as LDoPM
FROM cte_FirstDateofMonth
)
SELECT [Date],
DATENAME(dw, Date) AS DatofWeek,
CASE
WHEN DATENAME(dw, Date) = 'Sunday' OR DATENAME(dw, Date) = 'Saturday' THEN 0
ELSE
DATEDIFF(dd, LDoPM, Date)
- (DATEDIFF(wk, LDoPM, Date) * 2)
- (CASE
WHEN DATENAME(dw, Date) = 'Sunday' OR DATENAME(dw, Date) = 'Saturday' THEN 1
ELSE 0
END)
END AS WordkindDayNumber,
dbo.ufn_WordkindDayNumber(Date) as FN_WordkindDayNumber
FROM cte_LastDayofPreviousMonth;
答案 2 :(得分:0)
I created this solution which I think is simple, because you don't need to create a table:
DECLARE @Begin DATETIME = '20160628'
DECLARE @End DATETIME = '20160802 23:59'
;WITH Cte AS
(
SELECT
@Begin AS 'Dia'
,DATEPART(WEEKDAY,@Begin) AS DiaSemana
UNION ALL
SELECT
CteADD.Dia
,DATEPART(WEEKDAY,CteADD.Dia) AS DiaSemana
FROM
Cte
CROSS APPLY (SELECT DATEADD(DD,1,Cte.Dia) AS Dia ) CteADD
WHERE
CteADD.Dia < @End
)
SELECT
DiaSemana
,COUNT(DiaSemana) AS 'QntDias'
FROM
Cte
GROUP BY
DiaSemana