如何用IN替换INNER JOIN?

时间:2013-10-04 18:27:06

标签: sql sql-server sql-server-2008 join

我有一个存储过程在WHILE循环中运行几个查询,特别是这些查询比SP的其余部分指数长得多,这大大降低了我的性能。

我已经在一些地方读过,如果您只是从第一个表中提取列,那么使用ININNER JOIN可以提高性能,这正是我正在做的事情

然而,问题是我没有第一个线索可以用INNER JOIN子句替换IN。我认为IN的语法与INNER JOIN非常不同,但我不知道从哪里开始。

作为一个脚注,SQL不是我的强项。非常感谢所有建议。

这是其中一个查询。它们在逻辑上几乎完全相同。

SELECT @CurrentKey = riv.Key
FROM   ResourceInfo_VW riv
       INNER JOIN (SELECT Track,
                          Code,
                          [Language]
                   FROM   ResourceInfo_VW
                   WHERE  Key = @CurrentKey) AS riv2
         ON riv.Track = riv2.Track
            AND riv.Code = riv2.Code
            AND riv.[Language] = riv2.[Language]
       INNER JOIN UserGroupCourseCatalog_VW ugcc
         ON riv.Key = ugcc.Key
WHERE  riv.[Type] = 'a'
       AND ugcc.UserGroupKey = @UserGroupKey 

4 个答案:

答案 0 :(得分:2)

一个选项是创建一个表变量来存储中间结果。

首先在@UserGroupKey循环中插入while s。然后针对您的真实数据表运行单个update ... select。这将是该行动中最昂贵的部分。

表变量现在可以查找UserGroupKeyKey,并且执行速度比搜索原始表要快得多。

declare @t table (UserGroupKey nvarchar(255), Key nvarchar(255))
while (...)
begin

    insert into @t(UserGroupKey) values (@UserGroupKey)

end

-- this is the expensive part, but it only happens once
update @t
set Key = riv.KEY
FROM   ResourceInfo_VW riv
       INNER JOIN (SELECT Track,
                          Code,
                          [Language]
                   FROM   ResourceInfo_VW
                   WHERE  KEY = @Key) AS riv2
         ON riv.Track = riv2.Track
            AND riv.Code = riv2.Code
            AND riv.[Language] = riv2.[Language]
       INNER JOIN UserGroupCourseCatalog_VW ugcc
         ON riv.KEY = ugcc.KEY
WHERE  riv.[Type] = 'a'
       AND ugcc.UserGroupKey = @t.UserGroupKey 

while (...)
begin

    select @Key = Key
    from @t
    where @t.UserGroupKey = @UserGroupKey

end

答案 1 :(得分:2)

我注意到的第一件事是存在“相关子查询”,这实际上并不是必需的。 您已选择输入变量,这意味着即使存在多个KEY,也只会在最后选择一个值。 在这种情况下,在变量中选择哪个键取决于SQL服务器,因为没有order by子句。

考虑添加Top和order by,以便您知道在多行满足WHERE条件的情况下,将获得什么结果。 每次运行相同的查询时,结果应至少保持一致。

我会在下面重写查询。如果表上有适当的索引,性能应该不错。

请注意,添加了TOP 1,因为在变量中无论如何都无法存储多个值。因此,找出您要存储的ONE值。 MIN,MAX,TOP1等......

此外,我认为不需要对表“ResourceInfo_VW”进行SELF JOIN。如果我在这里错了,你可以纠正我。

SELECT 
TOP 1 
@Key= riv.KEY
FROM ResourceInfo_VW riv
INNER JOIN UserGroupCourseCatalog_VW ugcc
ON riv.KEY = ugcc.KEY AND riv.[Type] = 'a'
WHERE  ugcc.UserGroupKey = @UserGroupKey

只是为了说明,如果你试图理解为什么这个查询以当前的方式编写的逻辑,那么只有你可以进入下一步,在你的情况下,使用不同的运算符重写查询。

答案 2 :(得分:1)

是的格式非常不同,它们在技术上做了不同的事情: 这就是联接的完成方式:

SELECT * FROM TABLEA a JOIN TABLEB on a.commonfield = b.commonfield

这是你使用IN语句的方式

SELECT * FROM TABLEA WHERE commonfield in (SELECT commonfield from tableb)

答案 3 :(得分:0)

需要一些思考,但我通过从相关语句中删除所有INNER JOIN来大大优化了这种性能。

相对于运行所花费的时间,此查询会根据正在处理的记录数量而变得越来越快。

这是我最终的结果。你会注意到一些额外的变量。这些是在每次WHILE次迭代开始时设置的。

SELECT  @CurrentTrack = Track,
        @CurrentCode = Code,
        @CurrentLanguage = [Language]
FROM    ResourceInfo_VW riv
WHERE   riv.Key = @CurrentKey

SELECT      riv.Key
FROM        ResourceInfo_VW riv
WHERE       riv.[Type] = 'a'
        AND riv.Track = @CurrentTrack
        AND riv.Code = @CurrentCode
        AND riv.[Language] = @CurrentLanguage
        AND riv.CourseKey IN (SELECT CourseKey 
                              FROM  UserGroupCourseCatalog_VW 
                              WHERE UserGroupKey = @UserGroupKey)