在我们公司,对客户进行定期评估并为其评分。评估结果存储在数据库(SQL Server 2017)中,结果看起来像这样。
ClientID AssessID AssessMonth RepMonth AssessGrade
1 100 01/2018 01/2018 0.98
1 149 07/2018 07/2018 0.80
1 199 01/2019 01/2019 0.45
到目前为止,太好了。现在,来自监管机构的办公室已收到要求为他们提供每个报告月每个客户的评估等级的要求。这意味着我们需要为以后的每个ReportingMonth重复第一个记录,直到完成新的评估为止(或者,如果没有新的评估,则继续重复该记录)。使结果看起来像这样:
ClientID AssessID AssessMonth RepMonth AssessResult
1 100 01/2018 01/2018 0.98
1 100 01/2018 02/2018 0.98
1 100 01/2018 03/2018 0.98
1 100 01/2018 04/2018 0.98
1 100 01/2018 05/2018 0.98
1 100 01/2018 06/2018 0.98
1 149 07/2018 07/2018 0.80
1 149 07/2018 08/2018 0.80
1 149 07/2018 09/2018 0.80
1 149 07/2018 10/2018 0.80
1 149 07/2018 11/2018 0.80
1 149 07/2018 12/2018 0.80
1 199 01/2019 01/2019 0.45
您可能会看到重复每条记录,直到对该客户进行新评估为止。仅RepMonth会获得一个新值,该值比其前任值高一个。数据库中不存在介于两者之间的记录。
我可以生成一个表,其中包含所有可能的报告月份,但是我不知道如何获得期望的结果。
答案 0 :(得分:1)
按以下方式工作是可行的(我已经使用了测试数据,并使用开始和结束月份进行了参数设置):
DECLARE
@StartMonth date = '2019-01-01'
, @EndMonth date = '2019-04-01'
DECLARE @t table
(
ClientID int
, AssessID int
, AssessMonth date
, RepMonth date
, AssessGrade decimal(19, 2)
)
INSERT INTO @T
VALUES (1, 1, '2019-01-01', '2019-01-01', 0.5)
INSERT INTO @T
VALUES (1, 2, '2019-04-01', '2019-04-01', 0.9)
INSERT INTO @T
VALUES (2, 1, '2019-01-01', '2019-01-01', 0.4)
INSERT INTO @T
VALUES (2, 2, '2019-03-01', '2019-03-01', 0.3)
;
WITH cteMonths
AS
(
SELECT CAST(@EndMonth AS date) RepMonth
UNION ALL
SELECT DATEADD(MONTH, -1, RepMonth)
FROM cteMonths
WHERE DATEADD(MONTH, -1, RepMonth) >= @StartMonth
)
,
cteMonthsClients
AS
(
SELECT
M.RepMonth
, C.ClientID
FROM
cteMonths M
CROSS JOIN (SELECT DISTINCT ClientID FROM @t) C
)
SELECT
M.ClientID
, M.RepMonth
, ISNULL(T.AssessID, T2.AssessID) AssessID
, ISNULL(T.AssessMonth, T2.AssessMonth) AssessMonth
, ISNULL(T.AssessGrade, T2.AssessGrade) AssessGrade
FROM
cteMonthsClients M
LEFT JOIN @t T ON
M.RepMonth = T.RepMonth
AND M.ClientID = T.ClientID
OUTER APPLY
(
SELECT TOP 1
AssessID
, AssessMonth
, AssessGrade
FROM @t T2
WHERE
T2.ClientID = M.ClientID
AND T2.RepMonth < M.RepMonth
ORDER BY RepMonth DESC
) T2
ORDER BY
ClientID
, RepMonth
答案 1 :(得分:0)
这是另一种方法,您将必须使用日期维度表,该表将为您提供以下输出:
ClientID AssessID AssessMonth RepMonth AssessGrade
1 100 01/2018 01/2018 0.98
1 100 01/2018 02/2018 0.98
1 100 01/2018 03/2018 0.98
1 100 01/2018 04/2018 0.98
1 100 01/2018 05/2018 0.98
1 100 01/2018 06/2018 0.98
1 149 07/2018 07/2018 0.80
1 149 07/2018 08/2018 0.80
1 149 07/2018 09/2018 0.80
1 149 07/2018 10/2018 0.80
1 149 07/2018 11/2018 0.80
1 149 07/2018 12/2018 0.80
1 199 01/2019 01/2019 0.45
有以下内容:
--Create Assessment Table
DECLARE @Table1 AS TABLE
(
ClientID INT,
AssessID INT,
AssessMonth VARCHAR(MAX),
RepMonth VARCHAR(MAX),
AssessGrade NUMERIC(18,2)
)
INSERT INTO @Table1 VALUES
(1,100,'01/2018','01/2018',0.98),
(1,149,'07/2018','07/2018',0.80),
(1,199,'01/2019','01/2019',0.45)
--Dummy date dimension table
DECLARE @MonthYear AS TABLE
(
[Month] VARCHAR(10),
[Year] VARCHAR(10),
[MonthYear] AS [Month] +'/'+ [Year]
)
INSERT INTO @MonthYear VALUES
('01',2017),('02',2017),('03',2017),('04',2017),('05',2017),('06',2017),('07',2017),('08',2017),('09',2017),('10',2017),('11',2017),('12',2017),
('01',2018),('02',2018),('03',2018),('04',2018),('05',2018),('06',2018),('07',2018),('08',2018),('09',2018),('10',2018),('11',2018),('12',2018),
('01',2019),('02',2019),('03',2019),('04',2019),('05',2019),('06',2019),('07',2019),('08',2019),('09',2019),('10',2019),('11',2019),('12',2019),
('01',2020),('02',2020),('03',2020),('04',2020),('05',2020)
--Final select statement
SELECT
t.ClientID,
t.AssessID,
t.AssessMonth,
m.MonthYear AS RepMonth,
t.AssessGrade
FROM
@Table1 t
CROSS JOIN @MonthYear m
OUTER APPLY
(
SELECT TOP 1
AssessMonth
FROM
@Table1
WHERE
AssessID > t.AssessID
ORDER BY AssessID
) o
OUTER APPLY
(
SELECT TOP 1
AssessMonth
FROM
@Table1
ORDER BY
AssessID DESC
) o2
WHERE
(CAST(RIGHT('0' + RIGHT(m.MonthYear, 4) + LEFT(m.MonthYear, 2), 6) AS INT) < CAST(RIGHT('0' + RIGHT(o.AssessMonth, 4) + LEFT(o.AssessMonth, 2), 6) AS INT)
OR (O2.AssessMonth = t.AssessMonth AND CAST(RIGHT('0' + RIGHT(m.MonthYear, 4) + LEFT(m.MonthYear, 2), 6) AS INT) <= CAST(RIGHT('0' + RIGHT(o2.AssessMonth, 4) + LEFT(o2.AssessMonth, 2), 6) AS INT)))
AND CAST(RIGHT('0' + RIGHT(m.MonthYear, 4) + LEFT(m.MonthYear, 2), 6) AS INT) >= CAST(RIGHT('0' + RIGHT(t.AssessMonth, 4) + LEFT(t.AssessMonth, 2), 6) AS INT)
ORDER BY
t.ClientID, t.AssessID, M.Year, M.Month