집계 테이블 (일명 숫자 테이블)을 사용하여 날짜 테이블을 만드는 또 다른 방법이 있습니다. 내 의견에 유의하십시오.
-- Build the source data table.
declare @t table(Name nvarchar(10), InsertDate date, Size int);
insert into @t values
('john','20150630',1 )
,('john','20160110',10 )
,('john','20160112',100)
,('john','20160305',1000)
,('doe' ,'20160101',1 );
-- A year is fine, don't need a date data type
declare @year smallint = 2016;
WITH -- dummy rows for a tally table:
E AS (SELECT E FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(e)),
dateRange(totalDays, mn, mx) AS -- Get the range and number of months to create
(
SELECT DATEDIFF(MONTH, MIN(InsertDate), MAX(InsertDate)), MIN(InsertDate), MAX(InsertDate)
FROM @t
),
iTally(N) AS -- Tally Oh! Create an inline Tally (aka numbers) table starting with 0
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1))-1
FROM E a CROSS JOIN E b CROSS JOIN E c CROSS JOIN E d
),
RunningTotal AS -- perform a running total by year/month for each person (Name)
(
SELECT
yr = YEAR(DATEADD(MONTH, n, mn)),
mo = MONTH(DATEADD(MONTH, n, mn)),
Name,
Size = SUM(Size) OVER
(PARTITION BY Name ORDER BY YEAR(DATEADD(MONTH, n, mn)), MONTH(DATEADD(MONTH, n, mn)))
FROM iTally
CROSS JOIN dateRange
LEFT JOIN @t ON MONTH(InsertDate) = MONTH(DATEADD(MONTH, n, mn))
WHERE N <= totalDays
) -- Final output will only return rows where the year matches @year:
SELECT
name = ISNULL(name, LAG(Name, 1) OVER (ORDER BY yr, mo)),
yr, mo,
size = ISNULL(Size, LAG(Size, 1) OVER (ORDER BY yr, mo))
FROM RunningTotal
WHERE yr = @year
GROUP BY yr, mo, name, size;
결과 :
name yr mo size
---------- ----------- ----------- -----------
doe 2016 1 1
john 2016 1 111
john 2016 2 111
john 2016 3 1111
당신은 당신이 외부 조인에 사용할 수있는 달력 테이블이 필요합니다. [this] (https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/) 또는 [this] (https : // sqlperformance .com/2013/01/t-sql-queries/generate-a-set-3). –
사실 몇 달 동안 몇 가지 정적 값을 왼쪽 외부 조인 테이블로 제공하려고했지만 길을 찾을 수 없었습니다. – sotn
정적 값은 무엇입니까? 또한 고객이 지난 2 년 동안 묻는 질문 일 경우 쿼리가 작동해야하므로 동적으로 작성하고 연도를 포함해야합니다. 일단 당신이 달력 테이블을 가지면 그렇게 어렵지 않습니다. 'MIN (InsertDate)'와 'MAX (InsertDate)'를 선택한 하위 쿼리로 연도 + 월 단위로 그룹화하고 시작 + 종료 날짜를 가져와야합니다. –