IN和JOIN之间的区别

时间:2012-05-30 06:10:27

标签: sql tsql sql-server-2005

我想知道下面提到的两个查询之间有什么区别,因为第一个在服务器上执行需要10秒以上,第二个在不到一秒的时间内执行...

更新 - 我 以下是从SQL Server复制和粘贴的实际查询及其执行计划(原样),对于我以前的查询造成的任何不便表示抱歉...... :(

SELECT  REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS ManagmentPlanDate
FROM    ManagmentPlan m
        INNER JOIN Product p ON p.Product_ID = m.ProductID
        INNER JOIN Category c ON c.C_ID = p.C_ID
        LEFT OUTER JOIN Employee e ON e.emp_no = m.PrescribedBy
        LEFT OUTER JOIN dbo.Issue_Stock i ON i.serial_no = m.IssueStockID
        INNER JOIN dbo.Units u ON u.U_ID = p.U_ID
WHERE   ( ( @PatientID IS NULL )
          AND ( @VisitID IS NULL )
          AND ( m.WardRegNo = @WardRegNo )
        )
        OR --Get only cuurent admission TP 
        ( ( @PatientID IS NULL )
          AND ( @WardRegNo IS NULL )
          AND ( VisitID = @VisitID
                AND m.WardRegNo IS NULL
              )
        )
        OR -- Get Only Current OPD visit TP 
        ( ( @WardRegNo IS NULL )
          AND ( @VisitID IS NULL )
          AND ( visitid IN ( SELECT id
                             FROM   PatientVisit
                             WHERE  PatientID = @PatientID ) )
        )
        OR --Get All Visits TP
        ( ( @PatientID IS NULL )
          AND ( @VisitID IS NOT NULL )
          AND ( @WardRegNo IS NOT NULL )
          AND ( ( VisitID = @VisitID )
                OR ( m.WardRegNo = @WardRegNo )
              )
        ) -- Get Current OPD visit and cuurent admission TP (Both)
        AND m.Deleted != 1
        AND m.PatientDeptID = @PatientDeptID
GROUP BY REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-')
ORDER BY CAST(REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS DATETIME) DESC

Execution Plan of the first Query

SELECT  REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS ManagmentPlanDate
FROM    ManagmentPlan m
WHERE   m.ProductID IN ( SELECT Product_ID
                         FROM   Product
                         WHERE  C_ID IN ( SELECT    C_ID
                                          FROM      Category )
                                AND U_ID IN ( SELECT    U_ID
                                              FROM      Units ) )
        AND m.PrescribedBy IN ( SELECT  Emp_no
                                FROM    Employee )
        AND m.IssueStockID IN ( SELECT  Serial_No
                                FROM    Issue_Stock )
        AND ( ( @PatientID IS NULL )
              AND ( @VisitID IS NULL )
              AND ( m.WardRegNo = @WardRegNo )
            )
        OR --Get only cuurent admission TP 
        ( ( @PatientID IS NULL )
          AND ( @WardRegNo IS NULL )
          AND ( VisitID = @VisitID
                AND m.WardRegNo IS NULL
              )
        )
        OR -- Get Only Current OPD visit TP 
        ( ( @WardRegNo IS NULL )
          AND ( @VisitID IS NULL )
          AND ( visitid IN ( SELECT id
                             FROM   PatientVisit
                             WHERE  PatientID = @PatientID ) )
        )
        OR --Get All Visits TP
        ( ( @PatientID IS NULL )
          AND ( @VisitID IS NOT NULL )
          AND ( @WardRegNo IS NOT NULL )
          AND ( ( VisitID = @VisitID )
                OR ( m.WardRegNo = @WardRegNo )
              )
        ) -- Get Current OPD visit and cuurent admission TP (Both)
        AND m.Deleted != 1
        AND m.PatientDeptID = @PatientDeptID
GROUP BY REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-')
ORDER BY CAST(REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS DATETIME) DESC

enter image description here

虽然,它解决了我的查询速度或优化问题,但只是好奇这两个查询之间究竟有什么区别,因为我认为第一个转换为第二个......

更新 - 我 正如您所看到的,两个查询只有 JOINS 转换为 IN 语句...

2 个答案:

答案 0 :(得分:2)

首先,您的第一个语句从两个 ProductsCategory表中检索所有匹配的记录,而您的第二个语句仅从Products检索所有匹配的行

如果将第一个语句更改为

,性能差异是什么
SELECT p.*
FROM   Products p
       INNER JOIN Category c ON p.CatNo = c.CatNo

修改

(如Martin所述)请注意,如果CatNo表中Category是唯一的,则两个语句的行数相同。 INNER JOIN将返回与Category表中的记录一样多的记录,而IN语句将返回与CatNo中唯一Category一样多的记录} table。

答案 1 :(得分:0)

in子句过滤从产品返回的行。内部联接将类别中的列添加到select语句输出中。