好的,这是我第二次尝试解决这个问题。
我想知道是否有可能的方法来优化为存储过程创建的游标,用于迭代带有两个联合的大选择语句。稍后,存储过程开始将值插入到临时表中,根据"在不存在的情况下检查每个值"选择陈述。
或者更好的是,是否可以使用select语句创建所有这些并且可能加入。
插入过程需要很长时间才能完成,我会重新选择数据会更快。
以下是SQL的一个示例:
declare @ID1 varchar(40) ,
@ID2 varchar(20) ,
@State varchar(20) ,
@isActive bit
Declare CuTable SCROLL INSENSITIVE cursor for
Select
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AT' AS [State],
CASE When (isAvtiveDate > { fn CURDATE() }) or isAvtiveDate is null Then 1 else 0 end AS isAvtive
From
server1.db.dbo.table1
Inner Join
server1.db.dbo.table2 on ID2 = ID1
Where ID3 = 1 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
Select
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AP' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
From
server1.db.dbo.table1
Inner Join
server1.db.dbo.table2 on ID2 = ID1
Where
ID3 = 2 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
Select
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AH' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
From server1.db.dbo.table1 inner join server1.db.dbo.table2 on ID2 = ID1
inner join server1.db.dbo.table13 on ID2 = ID4
Where ID3 = 5 and toDate is null and fromDate is not null AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
Open CuTable
Fetch Next From CuTable Into @ID1, @ID2, @[State], @isActive
While @@Fetch_Status = 0
Begin
Insert Into StagingTable (ID1, ID2, [State], isActive)
--Values
Select @ID1, @ID2, @[State], @isActive
where not exists(select * from StagingTable where ID1 = @ID1 and ID2 = @ID2)
Fetch Next From CuTable Into @ID1, @ID2, @[State], @isActive
End
close CuTable
deallocate CuTable
HEADS UP:我正在使用SQL SERVER 2005
答案 0 :(得分:0)
根本不需要光标,因为数据没有动态变化。您应该能够使用基于集合的方法执行此操作。下面是使用CTE的示例,左连接仅插入登台表中不存在的那些:
;WITH CTE AS
(
SELECT CAST(ID1 as Varchar(20)) AS ID1,
CAST(ID2 as Varchar(20)) AS ID2,
'AT' AS [State],
CASE When (isAvtiveDate > { fn CURDATE() }) or isAvtiveDate is null Then 1 else 0 end AS isAvtive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 on ID2 = ID1
WHERE ID3 = 1 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
SELECT CAST(ID1 as Varchar(20)) AS ID1,
CAST(ID2 as Varchar(20)) AS ID2,
'AP' AS [State],
CASE WHEN (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 on ID2 = ID1
WHERE ID3 = 2 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
SELECT
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AH' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 ON ID2 = ID1
INNER JOIN server1.db.dbo.table13 ON ID2 = ID4
WHERE ID3 = 5 and toDate is null and fromDate is not null AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
)
INSERT INTO StagingTable
(
ID1,
ID2,
[State],
isActive
)
SELECT DISTINCT
CT.ID1,
CT.ID2,
CT.[State],
CT.isActive
FROM CTE AS CT
LEFT JOIN StagingTable AS ST ON ST.ID1 = CT.ID1 AND ST.ID2 = CT.ID2
WHERE ST.ID1 IS NULL
AND ST.ID2 IS NULL;
鉴于需要像游标一样检查每一行,我将使用以下内容,使用临时表检查每个ID1和ID2集合,当插入临时表时,标识是唯一的,然后执行插入操作临时表中的临时表:
/*Create temp table*/
IF OBJECT_ID('tempdb..#tmpData') IS NOT NULL DROP TABLE #tmpData
GO
CREATE TABLE #tmpData
(
ID1 VARCHAR(20) ,
ID2 VARCHAR(20) ,
[State] VARCHAR(2) ,
IsActiveData BIT
)
/*Insert into the temp table, with each insert join back to the temp table to ensure ID1 and ID2 are not already inserted*/
INSERT INTO #tmpData
(
ID1 ,
ID2 ,
[State] ,
IsActiveData
)
SELECT CAST(ID1 as Varchar(20)) AS ID1,
CAST(ID2 as Varchar(20)) AS ID2,
'AT' AS [State],
CASE WHEN (isAvtiveDate > { fn CURDATE() }) or isAvtiveDate is null Then 1 else 0 end AS isAvtive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 on ID2 = ID1
WHERE ID3 = 1 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
INSERT INTO #tmpData
(
ID1 ,
ID2 ,
[State] ,
IsActiveData
)
SELECT CAST(T1.ID1 as VARCHAR(20)) AS ID1,
CAST(T2.ID2 as VARCHAR(20)) AS ID2,
'AP' AS [State],
CASE WHEN (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1 AS T1
INNER JOIN server1.db.dbo.table2 AS T2 ON T2.ID2 = T1.ID1
LEFT JOIN #tmpData AS T ON T.ID1 = T1.ID1 AND T.ID2 = T2.ID2
WHERE ID3 = 2 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
AND T.ID1 IS NULL
AND T.ID2 IS NULL
INSERT INTO #tmpData
(
ID1 ,
ID2 ,
[State] ,
IsActiveData
)
SELECT
Cast(T1.ID1 as Varchar(20)) AS ID1,
Cast(T2.ID2 as Varchar(20)) AS ID2,
'AH' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) OR isActiveDate IS NULL Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1 AS T1
INNER JOIN server1.db.dbo.table2 AS T2 ON T2.ID2 = T1.ID1
INNER JOIN server1.db.dbo.table13 AS T13 ON T2.ID2 = T13.ID4
LEFT JOIN #tmpData AS T ON T.ID1 = T1.ID1 AND T.ID2 = T2.ID2
WHERE ID3 = 5
AND toDate IS NULL
AND fromDate IS NOT NULL
AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
AND T.ID1 IS NULL
AND T.ID2 IS NULL
/*Insert into the staging table from the temp table ensuring only records that are not already in there are inserted.*/
INSERT INTO StagingTable
(
ID1,
ID2,
[State],
isActive
)
SELECT CT.ID1,
CT.ID2,
CT.[State],
CT.isActive
FROM #tmpData AS CT
LEFT JOIN StagingTable AS ST ON ST.ID1 = CT.ID1 AND ST.ID2 = CT.ID2
WHERE ST.ID1 IS NULL
AND ST.ID2 IS NULL;