Ваша проблема в этой части:
IF (@old_enroll_mth <> @enroll_mth)
BEGIN
SELECT @active_count = @active_count - @tot_cancel
SELECT @intial = 'N'
END
ELSE
BEGIN
SELECT @active_count = @tot_orders - @tot_cancel
SELECT @intial = 'Y'
END
вы перевернули нужную логику;) .. так что вам нужно, чтобы она была такой:
IF (@old_enroll_mth <> @enroll_mth)
BEGIN
SELECT @active_count = @tot_orders - @tot_cancel
SELECT @intial = 'Y'
END
ELSE
BEGIN
SELECT @active_count = @active_count - @tot_cancel
SELECT @intial = 'N'
END
ОБНОВЛЕНО
ОБРАЗЦЫ ДАННЫХ
DECLARE @summary TABLE (enroll_month datetime, tot_orders int)
DECLARE @detail TABLE (enroll_month datetime, cncl_mnth datetime, mth int, tot_cancel int)
DECLARE @attr TABLE (enroll_month datetime ,cncl_mth datetime, mth int, tot_orders int,tot_cancel int, active_count int, attr_rate int , retn_rate int)
insert into @summary(enroll_month, tot_orders) values
('2017-01-01 00:00:00.000', 390),
('2017-02-01 00:00:00.000', 615)
insert into @detail(enroll_month,cncl_mnth,mth,tot_cancel) values
('2017-01-01 00:00:00.000', '2017-01-01 00:00:00.000', 1, 160),
('2017-01-01 00:00:00.000','2017-02-01 00:00:00.000', 2, 26),
('2017-01-01 00:00:00.000','2017-03-01 00:00:00.000', 3, 23)
Используя приведенный выше пример, и ваш CURSOR
(с изменением вышеуказанной логики - перевернутый):
DECLARE
@enroll_mth datetime ,@cncl_mth datetime, @mth int ,
@tot_orders numeric, @tot_cancel numeric,
@attr_rate numeric(6,2), @retn_rate numeric(6,2),
@active_count int
DECLARE att_cursor CURSOR FOR
SELECT
d.Enroll_Month, d.cncl_mnth, d.mth,
s.tot_orders, d.tot_cancel
FROM @summary s, @Detail d
WHERE
s.Enroll_Month = d.Enroll_Month
OPEN att_cursor
FETCH NEXT FROM att_cursor INTO @enroll_mth, @cncl_mth, @mth, @tot_orders, @tot_cancel
DECLARE
@old_enroll_mth datetime,
@old_cncl_mth datetime, @old_mth int, @month datetime ,
@intial varchar(1),
@old_active_cnt int, @old_tot_cancel int,
@old_retn_rate numeric(6,2), @old_attr_rate numeric(6,2),
@counter int
SELECT @old_enroll_mth = ''
SELECT @intial = 'Y'
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@old_enroll_mth <> @enroll_mth)
BEGIN
SELECT @active_count = @tot_orders - @tot_cancel
SELECT @intial = 'Y'
END
ELSE
BEGIN
SELECT @active_count = @active_count - @tot_cancel
SELECT @intial = 'N'
END
SELECT @retn_rate = (@active_count / @tot_orders) * 100
SELECT @attr_rate = 100 - @retn_rate
INSERT INTO @attr (enroll_month, cncl_mth, mth, tot_orders, tot_cancel, active_count, attr_rate, retn_rate )
VALUES (@enroll_mth, @cncl_mth, @mth, @tot_orders, @tot_cancel, @active_count, @attr_rate, @retn_rate)
SELECT @old_enroll_mth = @enroll_mth
SELECT @old_mth = @mth
SELECT @old_retn_rate = @retn_rate
SELECT @old_attr_rate = @attr_rate
SELECT @old_active_cnt = @active_count
SELECT @old_cncl_mth = @cncl_mth
SELECT @old_tot_cancel = @tot_cancel
FETCH NEXT FROM att_cursor INTO @enroll_mth, @cncl_mth, @mth, @tot_orders, @tot_cancel
END
CLOSE att_cursor
DEALLOCATE att_cursor
SELECT * FROM @attr
Если вы хотите принять другой метод без CURSOR
или CTE
, тогда вы можете использовать это вместо:
SELECT
D.Enroll_Month
, cncl_mnth
, mth
, tot_orders
, tot_cancel
, tot_orders - total_cancel active_count
, 100 - CAST(CAST((tot_orders - total_cancel) AS DECIMAL(18,2) ) / (tot_orders) * 100 AS DECIMAL(18,2) ) attr_rate
, CAST(CAST((tot_orders - total_cancel) AS DECIMAL(18,2) ) / (tot_orders) * 100 AS DECIMAL(18,2) ) retn_rate
FROM (
SELECT
d.Enroll_Month
, d.cncl_mnth
, d.mth
, s.tot_orders
, d.tot_cancel
, SUM(d.tot_cancel) OVER(PARTITION BY d.Enroll_Month ORDER BY mth ROWS UNBOUNDED PRECEDING) total_cancel
FROM @summary s
JOIN @Detail d ON s.Enroll_Month = d.Enroll_Month
) D