目前这个SQL需要大约1.5小时才能运行。我试图删除游标(使用CTE和递归),但我找不到合适的解决方案,因为它具有基于日期的运行总计。此外,还会在游标中删除数据
正如您在代码中看到的那样,我们在另一个中有两个游标。第一个光标中有40K记录。任何想法如何改进。
SET NOCOUNT ON
DECLARE @chg_type AS char(4);
DECLARE @chg_date AS datetime;
DECLARE @Salary AS char(9);
DECLARE @chg_factor AS numeric(13, 6);
DECLARE @to_Salary AS char(9);
DECLARE @Salary_permid AS char(9);
DECLARE @to_Salary_permid AS char(9);
DECLARE @income AS int;
DECLARE @cost AS numeric(13, 0);
DECLARE @ReportDate AS datetime;
DECLARE @lagDate AS datetime;
DECLARE @na AS numeric(18, 2);
DECLARE @system_date AS datetime;
DECLARE @count1 AS int;
DECLARE @counter AS int = 0;
SET @system_date = GETDATE();
DROP TABLE #Temptable_ReportDate
CREATE TABLE #Temptable_ReportDate (
income int,
Salary char(9),
cost numeric(13, 0),
ReportDate datetime
);
DROP TABLE #Temptable_LagDate
CREATE TABLE #Temptable_LagDate (
income int,
Salary char(9),
cost numeric(13, 0),
lagDate datetime
);
DROP TABLE #cc
CREATE TABLE #cc (
chg_type char(4),
chg_date datetime,
Salary char(9),
chg_factor numeric(13, 6),
to_Salary char(9)
);
CREATE INDEX idx_c_ReportDate_income ON #Temptable_ReportDate (income)
CREATE INDEX idx_c_ReportDate_Salary ON #Temptable_ReportDate (Salary)
CREATE INDEX idx_c_lagDate_income ON #Temptable_LagDate (income)
CREATE INDEX idx_c_lagDate_Salary ON #Temptable_LagDate (Salary)
--Delete from #Temptable_ReportDate;
--insert into #Temptable_ReportDate
-- SELECT salaryHistory.income, salaryHistory.Salary, salaryHistory.cost,
-- salaryHistory.ReportDate
-- FROM
-- dbo.salaryHistory salaryHistory
-- inner join salaryMaster_full_view p on p.income = salaryHistory.income and p.ReportDate = salaryHistory.ReportDate
-- ORDER BY salaryHistory.Salary
DECLARE salaryMaster_cursor CURSOR FOR
SELECT
income,
ReportDate,
lagDate
FROM salaryMaster_full_view
WHERE ReportDate < @system_date
OR lagDate < @system_date
ORDER BY income
OPEN salaryMaster_cursor
BEGIN
FETCH NEXT
FROM salaryMaster_cursor
INTO @income,
@ReportDate,
@lagDate
WHILE @@Fetch_status = 0
BEGIN
SET @counter = @counter + 1;
PRINT @counter;
DELETE FROM #Temptable_ReportDate;
DELETE FROM #Temptable_LagDate;
INSERT INTO #Temptable_ReportDate
SELECT
salaryHistory.income,
salaryHistory.Salary,
salaryHistory.cost,
salaryHistory.ReportDate
FROM dbo.salaryHistory salaryHistory
WHERE salaryHistory.income = @income
AND salaryHistory.ReportDate = @ReportDate
ORDER BY salaryHistory.Salary
INSERT INTO #Temptable_LagDate
SELECT
salaryHistory.income,
salaryHistory.Salary,
salaryHistory.cost,
salaryHistory.ReportDate
FROM dbo.salaryHistory salaryHistory
WHERE salaryHistory.income = @income
AND salaryHistory.ReportDate = @lagDate
ORDER BY salaryHistory.Salary
--select * from #Temptable_ReportDate
IF @ReportDate < @system_date
BEGIN
DELETE FROM #cc;
WITH hh_cte
AS (SELECT
c.Salary,
c.chg_date,
c.to_Salary
FROM SalaryChange c
INNER JOIN #Temptable_ReportDate hh
ON hh.Salary = c.Salary
--inner join salaryMaster p on hh.income = p.income and p.ReportDate = hh.ReportDate
WHERE c.chg_type <> ('SUN')
AND hh.income = @income
-- and c.Salary = '204412100'
AND NOT (
c.chg_type IN ('MON',
'TUE',
'WED')
AND chg_factor = 0)
AND chg_date > hh.ReportDate
AND chg_date < @system_date),
cap_change_cte
AS (SELECT
c.*
FROM hh_cte c
UNION ALL
SELECT
c.Salary,
c.chg_date,
c.to_Salary
FROM SalaryChange c
INNER JOIN cap_change_cte cc
ON cc.to_Salary = c.Salary
--and c.to_Salary!= c.Salary
WHERE c.chg_type <> ('SUN')
AND NOT (
c.chg_type IN ('MON',
'TUE',
'WED')
AND c.chg_factor = 0)
-- AND c.chg_date > cc.ReportDate
AND c.chg_date < @system_date
AND cc.chg_date < c.chg_date)
INSERT INTO #cc
SELECT
chg_type,
chg_date,
Salary,
chg_factor,
to_Salary
FROM SalaryChange
WHERE Salary IN (SELECT DISTINCT
cc.Salary
FROM cap_change_cte cc)
DECLARE salary_changes CURSOR FOR
SELECT
cc.chg_type,
cc.chg_date,
cc.Salary,
cc.chg_factor,
cc.to_Salary
FROM #cc cc
ORDER BY cc.chg_date,
cc.Salary;
OPEN salary_changes
FETCH NEXT
FROM salary_changes
INTO @chg_type,
@chg_date,
@Salary,
@chg_factor,
@to_Salary
WHILE @@FETCH_STATUS = 0
BEGIN
SET @count1 = (SELECT
COUNT(*)
FROM #Temptable_ReportDate
WHERE income = @income
AND Salary = @Salary);
IF (@count1 > 0)
BEGIN
DECLARE @newcost AS numeric(13, 0);
DECLARE @count AS int;
SET @newcost = ROUND(@cost * @chg_factor, 0);
IF @chg_type IN ('MON',
'TUE')
BEGIN
SET @count = (SELECT
COUNT(*)
FROM #Temptable_ReportDate
WHERE income = @income
AND Salary = @to_Salary);
IF (@count > 0)
UPDATE #Temptable_ReportDate
SET cost = cost + @newcost,
Salary = @to_Salary
WHERE income = @income
AND Salary = @Salary;
ELSE
INSERT INTO #Temptable_ReportDate
VALUES (@income, @to_Salary, @newcost, @ReportDate);
END
ELSE
BEGIN
IF @Salary = @to_Salary
UPDATE #Temptable_ReportDate
SET cost = @newcost
WHERE income = @income
AND Salary = @Salary
ELSE
BEGIN
SET @count = (SELECT
COUNT(*)
FROM #Temptable_ReportDate
WHERE income = @income
AND Salary = @to_Salary);
IF (@count > 0)
BEGIN
UPDATE #Temptable_ReportDate
SET cost = cost + @newcost
FROM #Temptable_ReportDate
WHERE income = @income
AND Salary = @to_Salary
DELETE FROM #Temptable_ReportDate
WHERE income = @income
AND Salary = @Salary;
END
ELSE
UPDATE #Temptable_ReportDate
SET cost = @newcost,
Salary = @to_Salary
WHERE income = @income
AND Salary = @Salary;
END
END
END
FETCH NEXT
FROM salary_changes
INTO @chg_type,
@chg_date,
@Salary,
@chg_factor,
@to_Salary
END
CLOSE salary_changes
DEALLOCATE salary_changes
END
IF @lagDate < @system_date
BEGIN
DELETE FROM #cc;
WITH hh_cte
AS (SELECT
c.*
FROM SalaryChange c
INNER JOIN #Temptable_LagDate hh
ON hh.Salary = c.Salary
--inner join salaryMaster p on hh.income = p.income and p.ReportDate = hh.ReportDate
WHERE c.chg_type <> ('SUN')
AND hh.income = @income
-- and c.Salary = '204412100'
AND NOT (
c.chg_type IN ('MON',
'TUE',
'WED')
AND chg_factor = 0)
AND chg_date > hh.lagDate
AND chg_date < @system_date),
cap_change_cte
AS (SELECT
c.*
FROM hh_cte c
UNION ALL
SELECT
c.*
FROM SalaryChange c
INNER JOIN cap_change_cte cc
ON cc.to_Salary = c.Salary
--and c.to_Salary!= c.Salary
WHERE c.chg_type <> ('SUN')
AND NOT (
c.chg_type IN ('MON',
'TUE',
'WED')
AND c.chg_factor = 0)
-- AND c.chg_date > cc.ReportDate
AND c.chg_date < @system_date
AND cc.chg_date < c.chg_date)
INSERT INTO #cc
SELECT
chg_type,
chg_date,
Salary,
chg_factor,
to_Salary
FROM SalaryChange
WHERE Salary IN (SELECT
cc.Salary
FROM cap_change_cte cc)
DECLARE salary_changes CURSOR FOR
SELECT
cc.chg_type,
cc.chg_date,
cc.Salary,
cc.chg_factor,
cc.to_Salary
FROM #cc cc
ORDER BY cc.chg_date,
cc.Salary;
OPEN salary_changes
FETCH NEXT
FROM salary_changes
INTO @chg_type,
@chg_date,
@Salary,
@chg_factor,
@to_Salary
WHILE @@FETCH_STATUS = 0
BEGIN
SET @count1 = (SELECT
COUNT(*)
FROM #Temptable_LagDate
WHERE income = @income
AND Salary = @Salary);
IF (@count1 > 0)
BEGIN
SET @newcost = ROUND(@cost * @chg_factor, 0);
IF @chg_type IN ('MON',
'TUE')
BEGIN
SET @count = (SELECT
COUNT(*)
FROM #Temptable_LagDate
WHERE income = @income
AND Salary = @to_Salary);
IF (@count > 0)
UPDATE #Temptable_LagDate
SET cost = cost + @newcost,
Salary = @to_Salary
WHERE income = @income
AND Salary = @Salary;
ELSE
INSERT INTO #Temptable_LagDate
VALUES (@income, @to_Salary, @newcost, @lagDate);
END
ELSE
BEGIN
IF @Salary = @to_Salary
UPDATE #Temptable_LagDate
SET cost = @newcost
WHERE income = @income
AND Salary = @Salary
ELSE
BEGIN
SET @count = (SELECT
COUNT(*)
FROM #Temptable_LagDate
WHERE income = @income
AND Salary = @to_Salary);
IF (@count > 0)
BEGIN
UPDATE #Temptable_LagDate
SET cost = cost + @newcost
FROM #Temptable_LagDate
WHERE income = @income
AND Salary = @to_Salary
DELETE FROM #Temptable_LagDate
WHERE income = @income
AND Salary = @Salary;
END
ELSE
UPDATE #Temptable_LagDate
SET cost = @newcost,
Salary = @to_Salary
WHERE income = @income
AND Salary = @Salary;
END
END
END
FETCH NEXT
FROM salary_changes
INTO @chg_type,
@chg_date,
@Salary,
@chg_factor,
@to_Salary
END
CLOSE salary_changes
DEALLOCATE salary_changes
END;
--select * from #Temptable_ReportDate;
--select * from #Temptable_LagDate;
INSERT INTO salary_current_test (income, Salary, cost, na, cost_change, change_na, ReportDate, lagDate, cost_date, hold, release, change)
SELECT
ISNULL(#Temptable_ReportDate.income, #Temptable_LagDate.income) AS income,
ISNULL(#Temptable_ReportDate.Salary, #Temptable_LagDate.Salary) AS Salary,
SUM(ISNULL(#Temptable_ReportDate.cost, 0)) AS cost,
ISNULL(#Temptable_ReportDate.cost, 0) * 0 AS na,
SUM(ISNULL(#Temptable_ReportDate.cost, 0) - ISNULL(#Temptable_LagDate.cost, 0)) AS cost_change,
ISNULL(#Temptable_ReportDate.cost, 0) * 0 AS change_na,
ISNULL(#Temptable_ReportDate.ReportDate, @ReportDate) AS ReportDate,
ISNULL(#Temptable_LagDate.lagDate, @lagDate) AS lagDate,
GETDATE() AS cost_date,
0 AS hold,
0 AS release,
1 AS change
FROM #Temptable_ReportDate
FULL OUTER JOIN #Temptable_LagDate
ON #Temptable_ReportDate.Salary = #Temptable_LagDate.Salary
GROUP BY ISNULL(#Temptable_ReportDate.income, #Temptable_LagDate.income),
ISNULL(#Temptable_ReportDate.Salary, #Temptable_LagDate.Salary),
ISNULL(#Temptable_ReportDate.cost, 0) * 0,
ISNULL(#Temptable_ReportDate.cost, 0) * 0,
ISNULL(#Temptable_ReportDate.ReportDate, @ReportDate),
ISNULL(#Temptable_LagDate.lagDate, @lagDate)
ORDER BY 2
FETCH NEXT
FROM salaryMaster_cursor
INTO @income,
@ReportDate,
@lagDate
END
END
CLOSE salaryMaster_cursor
DEALLOCATE salaryMaster_cursor
SET NOCOUNT OFF
GO