我的SQL循环需要很长时间才能完成。有没有更好的方法来实现我的目标?
我正在尝试基于某些列对一组数据进行重复数据消除。也就是说,它不像只选择DISTINCT那么简单 我想从集合中选择列唯一的所有行。我对我的集合进行了排序,我只希望循环获取代理键列的第一个匹配项。我说的是proxy,因为它不是表的实际主键 我使用了while循环,并使用了一个基于临时表中行数的计数器变量。我在处理后从临时表中删除了每一行,这样就可以减少基础表中处理的一条记录和任何重复的行 虽然我的代码很好用,但它看起来很“牛仔气”,我想听听你对如何做到“更干净”的意见,谢谢 这是我的密码:我的SQL循环需要很长时间才能完成。有没有更好的方法来实现我的目标?,sql,sql-server,tsql,while-loop,Sql,Sql Server,Tsql,While Loop,我正在尝试基于某些列对一组数据进行重复数据消除。也就是说,它不像只选择DISTINCT那么简单 我想从集合中选择列唯一的所有行。我对我的集合进行了排序,我只希望循环获取代理键列的第一个匹配项。我说的是proxy,因为它不是表的实际主键 我使用了while循环,并使用了一个基于临时表中行数的计数器变量。我在处理后从临时表中删除了每一行,这样就可以减少基础表中处理的一条记录和任何重复的行 虽然我的代码很好用,但它看起来很“牛仔气”,我想听听你对如何做到“更干净”的意见,谢谢 这是我的密码: decl
declare @cnt int
set @cnt = (select COUNT(*) from #temp)
while @cnt > 0
begin
select top 1 * into #temp2 from #temp
insert into #temp3 (Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
select #temp2.*
from #temp2
left outer join #temp3 on #temp2.Member_ID = #temp3.Member_ID
where #temp3.Member_ID is null
delete #temp
from #temp
inner join #temp2 on #temp.Member_ID = #temp2.Member_ID
drop table #temp2
set @cnt = (select COUNT(*) from #temp)
end
如果我正确理解了您的需求,那么您希望将temp中的行插入temp3,但您希望确保只插入同一成员的一行。在这种情况下,您可以使用ROW_NUMBER和filter for ROW_NUMBER=1来确保只插入重复成员ID中的一行。然后添加“不存在”筛选器以避免插入已存在的行:
INSERT INTO #temp3 (Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
SELECT
Member_ID,
email,
meeting_status,
member_type,
firstname,
lastname,
address1,
Match_Method,
Match_Score
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER (PARTITION BY Member_ID ORDER BY (SELECT NULL))
FROM #temp
) t
WHERE
t.Rn = 1
AND NOT EXISTS (
SELECT 1
FROM #temp3 t3
WHERE t3.Member_ID = t.MEMBER_ID
)
如果我正确理解了您的需求,那么您希望将temp中的行插入temp3,但您希望确保只插入同一成员的一行。在这种情况下,您可以使用ROW_NUMBER和filter for ROW_NUMBER=1来确保只插入重复成员ID中的一行。然后添加“不存在”筛选器以避免插入已存在的行:
INSERT INTO #temp3 (Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
SELECT
Member_ID,
email,
meeting_status,
member_type,
firstname,
lastname,
address1,
Match_Method,
Match_Score
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER (PARTITION BY Member_ID ORDER BY (SELECT NULL))
FROM #temp
) t
WHERE
t.Rn = 1
AND NOT EXISTS (
SELECT 1
FROM #temp3 t3
WHERE t3.Member_ID = t.MEMBER_ID
)
在循环中,您不必每次都重新计算表的数量。您可以简单地减少@cnt。
您不应该每次在循环中都重新创建temp2。你可以重复使用它
您根本不必使用temp2。您只需使用select top 1*from temp即可
您根本不必使用循环,只需使用以下脚本即可:
insert into #temp3(Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
select *
from #temp
where Member_ID not in (select Member_ID from #temp3)
在循环中,您不必每次都重新计算表的数量。您可以简单地减少@cnt。
您不应该每次在循环中都重新创建temp2。你可以重复使用它
您根本不必使用temp2。您只需使用select top 1*from temp即可
您根本不必使用循环,只需使用以下脚本即可:
insert into #temp3(Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
select *
from #temp
where Member_ID not in (select Member_ID from #temp3)
备选案文1:
使用以下代码:
WITH uniqueRecords AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY T.Member_ID ORDER BY (SELECT 1)) AS RowNum
FROM #Temp AS T
)
INSERT INTO #temp3(Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
SELECT U.Member_ID, U.email, U.meeting_status,U.member_type,U.firstname,U.lastname,U.address1, U.Match_Method, U.Match_Score
FROM uniqueRecords AS U
LEFT OUTER JOIN #temp3 T3 on U.Member_ID = T3.Member_ID
WHERE U.RowNum=1
AND T3.Member_ID is null;
备选案文2:
我使用IGNORE\u DUP\u KEY=on在Member\u ID列的temp3上创建唯一索引
CREATE UNIQUE INDEX UX_temp3 ON #temp3 (Member_ID) WITH (IGNORE_DUP_KEY=ON);
ii插入temp和temp3左连接的结果。“忽略重复”键选项将忽略重复项
备选案文1:
使用以下代码:
WITH uniqueRecords AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY T.Member_ID ORDER BY (SELECT 1)) AS RowNum
FROM #Temp AS T
)
INSERT INTO #temp3(Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
SELECT U.Member_ID, U.email, U.meeting_status,U.member_type,U.firstname,U.lastname,U.address1, U.Match_Method, U.Match_Score
FROM uniqueRecords AS U
LEFT OUTER JOIN #temp3 T3 on U.Member_ID = T3.Member_ID
WHERE U.RowNum=1
AND T3.Member_ID is null;
备选案文2:
我使用IGNORE\u DUP\u KEY=on在Member\u ID列的temp3上创建唯一索引
CREATE UNIQUE INDEX UX_temp3 ON #temp3 (Member_ID) WITH (IGNORE_DUP_KEY=ON);
ii插入temp和temp3左连接的结果。“忽略重复”键选项将忽略重复项
感谢斯拉瓦的评论。但是,如果A在temp中存在两次,它仍将两次插入temp3,因为在生成“set”时,A在temp3中不存在,因此我在插入之前使用循环检查每一行。还是我完全迷路了。。。是否在每次插入后都重新检查temp3?如果temp表有完整的副本,则可以添加DISTINCT。如果重复项不完整,您必须定义规则:将插入哪些记录,哪些不插入。感谢Slava的评论。但是,如果A在temp中存在两次,它仍将两次插入temp3,因为在生成“set”时,A在temp3中不存在,因此我在插入之前使用循环检查每一行。还是我完全迷路了。。。是否在每次插入后都重新检查temp3?如果temp表有完整的副本,则可以添加DISTINCT。如果重复项不完整,则必须定义规则:将插入哪些记录,哪些不插入。是否在每次插入后再次检查“不存在”?@Craigoh1否,它将对整个选择进行评估。我会更新我的答案。我试过了,但它仍然插入了重复项,因此我使用循环和删除。你能解释一下分区位上的行数吗。。我以前从未见过这种情况。thanks@Craigoh1返回结果集中某个分区内的行的序列号,每个分区的第一行从1开始。因此,对ROW_NUMBER=1进行筛选将为每个分区只返回一行。是否在每次插入后再次执行“不存在”检查?@Craigoh1否,它将对整个选择进行评估。我会更新我的答案。我试过了,但它仍然插入了重复项,因此我使用循环和删除。你能解释一下分区位上的行数吗。。我以前从未见过这种情况。thanks@Craigoh1返回结果集中某个分区内的行的序列号,每个分区的第一行从1开始。因此,对ROW_NUMBER=1进行筛选将为每个分区只返回一行。我已以某种方式对集合进行排序。。。。不,不,你没有。您过去可能在任何时候使用过的任何订单都不再相关,除非您存储了
在一列或多列中排序信息时。具体来说,从temp中选择top 1*进入temp2可自由选择temp中的任意行。因此,如果第一个问题很重要,那么你的问题和答案中仍然缺少一些东西。但大多数答案都是一个好的开始。在SQL中,您的第一反应应该始终是如何处理整个集合,而不是逐行。如果我说将排序信息存储在一个或多个列中,我还应该在任何检索操作中说并在ORDER by子句中使用这些列,在这些检索操作中,此排序事项我以某种方式对集合进行了排序。。。。不,不,你没有。您在过去任何时候使用的任何排序都不再相关,除非您已将该排序信息存储在一个或多个列中。具体来说,从temp中选择top 1*进入temp2可自由选择temp中的任意行。因此,如果第一个问题很重要,那么你的问题和答案中仍然缺少一些东西。但大多数答案都是一个好的开始。在SQL中,您的第一反应应该始终是如何处理整个集合,而不是逐行处理。我说的是将排序信息存储在一列或多列中,在任何检索操作中,如果我在查询中注释掉惰性项并选择,那么我也应该在ORDERBY子句中使用这些列,而在您的查询中,这种排序是重要的。。它选择的行数与代码选择的行数完全相同,但只需大约18分钟。但是,插入正在抛出错误。。所以我只是把U.*改成了除RowNum thingy之外的所有字段。@Craigoh1很高兴它起到了作用。我已经编辑了ans。感谢您指出它:在您的查询中,如果我将惰性注释掉并选择。。它选择的行数与代码选择的行数完全相同,但只需大约18分钟。但是,插入正在抛出错误。。所以我只是把U.*改成了除RowNum thingy之外的所有字段。@Craigoh1很高兴它起到了作用。我已经编辑了ans。感谢您指出它: