SQL Server

월의 첫날, 월의 말일, 년의 첫날, 년의 말일, 문자열 일(DD)이 없는 달은 말일구하기

미스터몽키 2017. 12. 5. 14:41

특정일의 월의 첫날, 월의 말일 



declare @vdt date = '2017-12-08'    -- datatime 형도 가능
 
--첫날

SELECT DATEADD(DD, -DAY(@vdt) + 1, @vdt)

--> 2017-12-01

 
--말일1

SELECT DATEADD(D,-DAY(DATEADD(M,1,@vdt)), DATEADD(M,1,@vdt))
--> 2017-12-31

--말일2
SELECT DATEADD(MM, DATEDIFF(MM, -1, @vdt), -1)

--> 2017-12-31 00:00:00.000
 
cs




월의 첫날 구하기 원리는  특정일의 날수(Day()) 를 구하여 음수로 하면 전달 말일이 되고 

+1 을 하면 특정일의 월의 첫날이 된다.


--말일1의 월의 말일 구하기 원리는 다음달에서 날수만큼 음수로 특정일의 월의 말일이 된다.


--말일2의 월의 말일 구하기 원리는 ms-sql에서 날짜 기준은 1900-01-01 이다. 이것이 숫자로는 0이다.

날짜가 -1 은 1899-12-31 을 의미한다.

즉 DATEDIFF(MM, -1, @vdt) 는  1899년 12월 부터 특정월까지의 월수를 의미한다.

그리고 DATEADD로 '1899-12-31' 부터 월수만큼 더하므로 특정일의 월의 말일이 계산된다.


(추가) --------------------------------------------------------------------

SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) [올해 첫날] 

SELECT DATEADD(dd,-1,DATEADD(yy,0,DATEADD(yy,DATEDIFF(yy,0,getdate())+1,0))) [올해 말일]


(추가)  문자열 2자리 일(DD) 이 없는 달은 말일구하기 ('15', '28', '29', '30', '31' ...) 
매달 특정일에 어떤 업무를 처리해야 할때 특정일이 31일인 경우 어떤 달은 31일이 없을 수 있다. 
이런경우 해당월의 말일을 구하려면

DECLARE @PRE_YM   VARCHAR(8= '2018-02-';
DECLARE @DAY     DATE = '2018-02-09';
 
WITH VIEW1 AS
(
  SELECT '15' [REG_DD]
  UNION ALL
  SELECT '28' [REG_DD]
  UNION ALL
  SELECT '29' [REG_DD]
  UNION ALL
  SELECT '30' [REG_DD]
  UNION ALL
  SELECT '31' [REG_DD]
)
SELECT REG_DD,
CASE WHEN ISDATE(@PRE_YM + REG_DD) = 1 THEN  @PRE_YM + REG_DD
      ELSE DATEADD(D,-DAY(DATEADD(M,1,@DAY)), DATEADD(M,1,@DAY)) END [DT],
CASE WHEN ISDATE(@PRE_YM + REG_DD) = 1 THEN REG_DD 
      ELSE RIGHT(CONVERT(CHAR(8), DATEADD(D,-DAY(DATEADD(M,1,@DAY)), DATEADD(M,1,@DAY)), 112), 2) END [DD_],
DATEADD(D,-DAY(DATEADD(M,1,@DAY)), DATEADD(M,1,@DAY)) [END_DT]
FROM VIEW1 
 


---------------------------------
REG_DD DT         DD_ END_DT
15 2018-02-15 15 2018-02-28
28 2018-02-28 28 2018-02-28
29 2018-02-28 28 2018-02-28
30 2018-02-28 28 2018-02-28
31 2018-02-28 28 2018-02-28