问题
I was facing a problem on how to create a calculated column based on a column which contains dates. For example, I have a column which contains dates starting from July.
The DAY needs to be calculated as described in the picture using SQL server.
So basically can a column be created based on an existing column containing a lot of dates? I need this to be dynamic.
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
回答1:
With table, DateTable with a column Date of type Date, the following query will do what you ask.
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
回答2:
Based on the Title and subject, I am guessing that you want to try and identify the working day number of each month.
example:
1-Jan-14 is Wednesday so its Working day number 1
6-Jan-14 is Monday so its working day number 4 as (4-Jan-14 and 5-Jan-14 are Weekends)
Also the result should be a derived column in a table that already has data.
If the above is true then this is what I suggest
- Create a function to calculate the working days between two dates. (I have taken the last day of each oath as my initial date but you could also do +1 in you decide to go with first day of month way. (Personal preference really))
- Alter table and add calculated column that calls the function
Sample Query:
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;
Validation Script:
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;
回答3:
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
来源:https://stackoverflow.com/questions/24834975/count-of-weekdays-in-a-given-month