반응형
그냥 숫자만 있는 테이블 Copy_t. 그냥 1부터 999까지 있는 테이블을 사용하여
'202101' 숫자 여섯개 조건을 넣었을 때에 그 달 달력이 나오게 하는 쿼리를 만들어보려 했다.
나는 copy_t의 숫자들을 date의 day로 활용하였다. data_type변경 하는 데에 많은 함수가 쓰여졌다.
이전의 달력만들기 포스팅한 것과 차이점이 있는데 이전의 달력만들기에서는 1월달 달력이면 1월달만 표시 되었는데 여기서 만들려고 한 것은 1월달 달력이지만 전년도 12월의 마지막날들이 빈칸에 들어있고 1월 마지막 날 뒤에 다음달 2월의 처음 날짜들이 나오는 것이다.
CREATE TABLE #CALENDER01 (ID INT IDENTITY(1,1) PRIMARY KEY, YEAR INT, MONTH INT, D_DAY INT , WK INT , DW_NUM INT , DW_NAME NVARCHAR(50))
TRUNCATE TABLE #CALENDER01
DECLARE @INPUT_HERE VARCHAR(6) = '202201'
DECLARE @MONTH INT = 1
WHILE (@MONTH <= 3)
BEGIN
DECLARE @INPUT_DATE VARCHAR(6) = @INPUT_HERE
DECLARE @CALENDER VARCHAR(8) = @INPUT_DATE + '01'
SET @INPUT_DATE = LEFT(CONVERT(VARCHAR(6),DATEADD(M,@MONTH-2,CONVERT(DATETIME,@CALENDER)),112),6)
SET @CALENDER = @INPUT_DATE + '01'
INSERT INTO #CALENDER01 (YEAR,MONTH,D_DAY,WK, DW_NUM, DW_NAME)
SELECT
DATEPART(YYYY, CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)
ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END)) AS [YEAR],
DATEPART(MM, CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)
ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END)),
CP.NUM D_DAY,
CASE DATEPART(M,CONVERT(DATETIME,@INPUT_HERE+'01'))
WHEN 1
THEN CASE DATEPART(WK,CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END))-1 WHEN '52' THEN '0' ELSE DATEPART(WK,CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END))-1 END
ELSE CASE DATEPART(WK,CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END))-1 WHEN '0' THEN '52' ELSE DATEPART(WK,CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END))-1 END
END AS WK,
DATEPART(DW,
CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)
ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END)) AS DW_NUM,
DATENAME(DW,
CONVERT(DATETIME, CASE LEN(CP.NUM) WHEN '1' THEN @INPUT_DATE+'0'+CONVERT(VARCHAR(2), CP.NUM)
ELSE @INPUT_DATE+CONVERT(VARCHAR(2), CP.NUM)END)) AS DW_NAME
FROM COPY_T CP
WHERE CP.NUM BETWEEN 1 AND DATEDIFF(D,CONVERT(DATETIME, @CALENDER),DATEADD(M,1,CONVERT(DATETIME, @CALENDER)))
SET @MONTH = @MONTH + 1
END
SELECT
max(CASE DW_NUM WHEN '1' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS Su,
max(CASE DW_NUM WHEN '2' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS Mo,
max(CASE DW_NUM WHEN '3' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS Tu,
max(CASE DW_NUM WHEN '4' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS We,
max(CASE DW_NUM WHEN '5' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS Tr,
max(CASE DW_NUM WHEN '6' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS Fr,
max(CASE DW_NUM WHEN '7' THEN CONVERT(VARCHAR(2), D_DAY) ELSE '' END) AS Sa
FROM #CALENDER01 C
WHERE ID BETWEEN DATEPART(D,DATEADD(D,-1,DATEADD(M,-1,@CALENDER)))-DATEPART(DW,DATEADD(M,-1,@CALENDER))+2 AND DATEPART(D,DATEADD(D,-1,DATEADD(M,-1,@CALENDER)))+DATEPART(D,DATEADD(D,-1,@CALENDER))+(7-DATEPART(DW,DATEADD(D,-1,@CALENDER)))
GROUP BY WK
나는 3번 쿼리문을 돌려 입력한 날의 앞뒤전의 달까지 합쳐서 임시 테이블에 넣은 다음 중간을 뽑은 것이다. 하지만 여기서 힘들었던 것은 전달이 전년도인 경우를 어떻게 처리하는 가 였다. 그냥 임시테이블의 id로 처리를 하였다.
만약 1월 달력이 필요하다면 12,1,2월 달력을 뽑은 임시테이블의 딱 중간을 id로 가져오는 걸로 하였다. 중간을 가져오는 것은 where절 참고.
모범답안, 실무에 쓰인 쿼리문이다. 여기서는 copy_t의 숫자가 주(Week)로 활용이 되었고, 그로인해 쿼리문이 매우 짧아졌다. 그런 비주얼적인 갈무리가 덜 되었지만 기능 구현은 확실히 되었다.
select dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 0, convert(date, '202101' + '01', 112)),
dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 1, convert(date, '202101' + '01', 112)),
dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 2, convert(date, '202101' + '01', 112)),
dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 3, convert(date, '202101' + '01', 112)),
dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 4, convert(date, '202101' + '01', 112)),
dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 5, convert(date, '202101' + '01', 112)),
dateadd(dd, (-1) * (datepart(WEEKDAY, convert(date, '202101' + '01', 112)) - 1) + (cp.num - 1) * 7 + 6, convert(date, '202101' + '01', 112))
from copy_t cp
where cp.num <= datepart(week, dateadd(dd, -1, dateadd(month, 1, convert(date, '202101' + '01', 112)))) - datepart(week, convert(date, '202101' + '01', 112)) + 1
반응형
'Database > SQL Server' 카테고리의 다른 글
MS SQL, SQL Server - 스칼라 반환 함수 권한 허용 grant scalar valued function (0) | 2022.03.11 |
---|---|
MSSQL - SQL Server - SSMS 데이터베이스 용량, 테이블 당 건수 확인하기, 테이블당 데이터 개수 확인 (0) | 2022.01.26 |
SQL Server - 달력 만들기 (0) | 2021.01.08 |
SQL Server - 여러 행을 한 행에 담아 정리하기 (0) | 2020.12.30 |
SQL Server - 월별 max값 찾기, 월별 합계 및 총합계 뽑아내기 (1) | 2020.12.29 |