2011-07-25 26 views
1

月曜日から金曜日までの最終作業日数はどのように計算できますか?私の現在のスクリプトは、最後の月曜日の日付を取得しますが、私は最後の金曜日の日付を取得することはできません。 DATEPARTはあなたに曜日を取得する簡単な方法を提供しています仕事日 - 月曜日から金曜日までのTsqlを計算する

declare @StartDate datetime 
declare @EndDate datetime 


--Calculate date range for report 

select @EndDate = Cast(convert(char(10), getdate(), 101)+' 00:00:00' as datetime) 
select @StartDate = DateAdd(d, -7, @EndDate) 
select @EndDate = Cast(convert(char(10), getdate(), 101)+' 23:59:59' as datetime) 

select @StartDate startdate 
select @EndDate enddate 
+1

この質問はhttp://stackoverflow.com/questions/4025047/tsql-function-to-calculate-30-working-days-date-from-a-specified-date-sql-と非常によく似ていますサーバー –

+0

@Brian Dishawはい、多分それはその質問のように見えますが、与えられたコードは本当に良くなく、答えは受け入れられませんでした。 Btw Faiz、6つの質問と答えがまだ受け入れられていません –

答えて

2

助けてください:

SET DATEFIRST 1 -- monday is first day of the week 
SELECT DATEPART(weekday, '20110725') 
-- result is 1 

詳細についてはT-SQL Date functionsSET DATEFIRSTを参照してください。

曜日を使用すると、最後の月曜日と金曜日の前日の日数を計算し、(あなたが今やっているように)それらを計算するために 'AddDate'を使用することができます。

このタイプの期間選択には実際にDATEDIFFを使用する必要があります。 23時59分59秒までのすべてを選択すると、いくつかのレコードが除外される可能性が常にあります。たとえば23:59:59.001は範囲外ですが、それはまだ同じ日です。 DATEDIFFを使用すると、それが同じ日にあるかどうかテストして、時間部分を破棄することができます。文字列にキャストしたり、時間を追加したり、キャストバックしたりする必要はありません。

0

これら二つの質問:

は、いくつかの助けになるかもしれません。

最後の月曜日の検索方法はすでに分かっていますが、DATEADD()機能を使用して月曜日の日付に4日を追加すると、対応する金曜日を簡単に見つけることができます。たとえば、

SELECT @EndDate = DATEADD(DAY, 4, @StartDate) 
0

これはすべて今日の日付に関連しています。

だから、今日はDATEPART(weekday, getdate())

そして、調整変数にそれを回しているかを調べる - 例えば:

declare @adjustment int 
set @adjustment = CASE DATEPART(weekday, getdate()) WHEN 'MONDAY' THEN 0 WHEN 'TUESDAY' THEN 1, ...END 

それでは、あなたが望む月曜日は今日だろう - 7 - @adjustment
...金曜日月曜日+ 5

Declare @myMonday smalldatetime, 
     @myFriday smalldatetime 
set @myMonday = getdate() - 7 - @adjustment 
set @myFriday = @myMonday + 5 
1

になりたい答えは、人々が想定しているよりも、より複雑です。あなたが必要とするのは、5日前に戻って、その前の最初の月曜日、そしてそれ以降の最初の金曜日を見つけることです。 eatherは@@ datefirst、計算を使用したり、「firstdate 1を設定する」ことができます。私は最後のものを使用しないことを好みます。なぜなら、それは機能ではできないからです。ご覧のとおり、私は計算を使用しました。@ datefirstはまあまあです。

mondayの最後のグループを過去の金曜日にしたいとします。このクエリはそれを取得します。あなたが現在の月曜日を信じているならば、5日を追加して1分を引くことができます(私は信頼しません。月曜日にクエリを実行すると、最後の月曜日しか返されません)。

私のSQLでは、私は単純化を目指していません、私は有効性を目指しています。

DECLARE @getdate datetime = dateadd(day, cast(getdate() as int), 0) 
-- the 'Declare' can also be written like this thanks to @Andriy M 
--DECLARE @getdate = CAST(GETDATE() - 0.5 AS int) 
SELECT @getdate - 5 - CAST(@getdate- 5 as int) % 7 monday, 
dateadd(minute, -1, @getdate) - CAST(@getdate- 5 as int) % 7 friday 

結果:

Monday    Friday 
2011-07-18 0:00:00 2011-07-22 23:59:00 

*最初のソリューション@AndriyMがそれを指摘した一日オフだった、それが解決されています。


それは私が予想よりも異なる行動したいくつかの理由@Andriy M

への回答。私はそれを説明するが、夕方には最初の2つのフィールドが同じ値を持って、最後の2つのフィールドが同じ値を持っている午前中にこの

select cast(dateadd(day, cast(getdate() as int) - .5, 0) as datetime), 
cast(dateadd(day, cast(getdate() as int), 0) as datetime), 
cast(dateadd(day, cast(getdate() as int) + .5, 0) as datetime) 

を試すことができません。私はあなたと同じくらい驚いています。私はそれを説明することができればと思います。それは私があまりにもリングに私の帽子を投げるよここ http://data.stackexchange.com/stackoverflow/query/new

+0

あなたは 'キャスト(getdate()としてint)'で ' - 0.5'を使っていません、なぜですか?あなたは 'cast(datetime as int)'がdatetimeを切り捨てるのではなくラウンドさせることを知っていますか? –

+0

私は、 'cast( '20110725 18:00:00'としてdatetime)をintとしてキャストしています'キャスト(キャスト( '20110725 06:00:00'をdatetimeとして)int) '。 –

+0

@Andriy M Answerは私のスクリプトです –

0
DECLARE @my int 
DECLARE @myDeduct int 
DECLARE @day INT 
DECLARE @mydate DATETIME 

SET @mydate = '2012-08-01' 

SET @myDeduct = 0 
SET DateFirst 1 -- Set it monday=1 (value) 

--Saturday and Sunday on the first and last day of a month will Deduct 1 
IF (DATEPART(weekday,(DATEADD(dd,-(DAY(@mydate)-1),@mydate))) > 5) 
SET @myDeduct = @myDeduct + 1 

IF (DATEPART(weekday,(DATEADD(dd,-(DAY(DATEADD(mm,1,@mydate))),DATEADD(mm,1,@mydate)))) > 5) 
SET @myDeduct = @myDeduct + 1 

SET @my = day(DATEADD(dd,-(DAY(DATEADD(mm,1,@mydate))),DATEADD(mm,1,@mydate))) 

select (((@my/7) * 5 + (@my%7)) - @myDeduct) as Working_Day_per_month 
+0

これは面白いそこにいる誰かが知りたいと思っているという結果になりますが、実際には上記の質問に答えることはできません。上の別の一見を取る.. ;-) –

0

試験しました。 :-)

DECLARE @Date  datetime = '01/11/2015' 
DECLARE @StartDate datetime = DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6) -- MONDAY 
DECLARE @EndDate datetime = DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6) -- FRIDAY 

     SELECT '@Date'  as Variable ,CONVERT(date, @Date)  as DateValue ,DATENAME(dw, @Date)  as DayOfTheWeek 
UNION SELECT '@StartDate' as Variable ,CONVERT(date, @StartDate) as DateValue ,DATENAME(dw, @StartDate) as DayOfTheWeek 
UNION SELECT '@EndDate' as Variable ,CONVERT(date, @EndDate) as DateValue ,DATENAME(dw, @EndDate) as DayOfTheWeek 

-- Variable DateValue DayOfTheWeek 
-- ---------- ---------- ------------ 
-- @Date  2015-01-11 Sunday 
-- @StartDate 2015-01-05 Monday 
-- @EndDate 2015-01-09 Friday 

BONUS:同じテクニックを使用して5つの平日のクイックテーブルを生成することができます。ここで

SELECT DATENAME(dw, DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6))) as DayOfTheWeek 
     ,    DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6)) as DateValue 
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT 

-- DayOfTheWeek     DateValue 
-- ------------------------------ ----------------------- 
-- Monday       2015-01-05 00:00:00.000 
-- Tuesday      2015-01-06 00:00:00.000 
-- Wednesday      2015-01-07 00:00:00.000 
-- Thursday      2015-01-08 00:00:00.000 
-- Friday       2015-01-09 00:00:00.000 

は説明です:

1)まず、私たちは私たちからの評価を開始するために何日かを知る必要があります。この例では、日付値

SELECT @Date2 as DateValue, DATENAME(dw, @Date2) as DayOfTheWeek 
与えられ、ここで曜日の名前を取得するのボーナス技術を持っていてうれしいです)1月(日曜日)11日、2015年

DECLARE @Date2 datetime = '01/11/2015' 

図1bを使用することにしました1899年12月31日は1900年1月1日前に最初の日曜日です:

2)次に、私たちは与えられた曜日が数値的には1〜7

  • NOTEあるもの)米国のカレンダーに基づいて(確定知っておく必要がありますこれは最小値fまたはSmallDateTimeデータ型。
  • 注:はい、あなたはもっと単純に、このようDATEPART(DW、@Date)を使用することができますが、それは特定のサーバ環境が異なる構成
  • 結果かもしれないことを考えると、確定ではありません。1 =日曜日| 2 =月曜日| 3 =火曜日| 4 =水曜日| 5 =木曜日| 6 =金曜日| 7 =土曜日

    SELECT ((DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date2) % 7) + 1) [DayOfWeek Deterministic (Based on US)] 
    

3)さて、任意の日付を考えると、あなたは、任意の日付与えられ、今では特定の週

SELECT DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date2) % 7)), @Date2) as [Monday Day of the Week - Deterministic (Based on US)] 

4)のために月曜日を決定する決定論的な方法を持っている必要がありますあなたはその週の金曜日を決定する決定的な方法を持っているべきです

SELECT DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date2) % 7)), @Date2) as [Monday Day of the Week - Deterministic (Based on US)] 

5)最後の日付操作技術それ以前に平日の最初の一週間がある週に入る方法を知る必要があります。例えば、もし私たちが日曜日にいて、それから1日を引くと、土曜日に到着します。これは前週になります。これは平日の最初の一週間です。また、月曜日から1日を差し引くと、それは先週ではない日曜日にしか私たちを得ることができないので、1日を引くだけでは不十分です。裏返して、もし我々が土曜日にあって7日を引いたならば、前週の曜日はそれより前の週になります。ここでは、魔法の数字が何かを引くことができるかを理解するために分析を実行します。あなたは以下を参照することができますように、マジックナンバーは6

--           DAYS TO SUBTRACT 
-- Day of the Week  - 0  - 1  - 2  - 3  - 4  - 5  - 6  - 7 
-- ===============  ==== ==== ==== ==== ==== ==== ==== ==== 
-- Sunday    Bad  Good Good Good Good Good Good Good 
-- Monday    Bad  Bad  Good Good Good Good Good Good 
-- Tuesday    Bad  Bad  Bad  Good Good Good Good Good 
-- Wednesday   Bad  Bad  Bad  Bad  Good Good Good Good 
-- Thursday    Bad  Bad  Bad  Bad  Bad  Good Good Good 
-- Friday    Bad  Bad  Bad  Bad  Bad  Bad  Good Good 
-- Saturday    Good Good Good Good Good Good Good Bad 

BONUSあるあなたは少しテーブル内のすべての平日を持つようにしたい場合は)、あなたはまた、迅速なゼロベースの「集計表」を使用したいと思います。これを行うには多くの方法がありますので、あなたの味を選んでください。ここにはいくつかあります。

SELECT * FROM (SELECT 0 as DaysToAdd UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) as TT 
SELECT * FROM (SELECT TOP 5 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM sys.all_columns a CROSS JOIN sys.all_columns b) as TT 
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT 
関連する問題