带有' IN'的SQL查询在where子句中运行非常慢

时间:2018-05-08 16:27:17

标签: sql sql-server

我创建了一个运行的SQL查询,但需要大约17秒才能完成。我已将问题缩小到查询的Where部分中的IN子句。此部分还负责查找同一表中的所有记录,其中一条记录的kitref与多个其他记录的partofkit字段匹配。

有人可以帮助我提出如何提高效率的建议吗?

完整的SQL如下:

SELECT
    tblProductions.ProductionName, tblEquipment.KitRef, tblEquipment.PartOfKit, tblEquipment.Description, 
    tblCollection.HireID, tblCollection.CollectedBy, Format(tblCollection.DueBack,'dd/MM/yyyy') AS DueBack, Format(tblCollection.CollectionDate,'dd/MM/yyyy') AS CollectionDate, Format(tblCollection.CollectionTime,'HH:mm') AS CollectionTime, tblCollection.DiscountPC, 
    tblCollectionItemized.HireLine, tblCollectionItemized.Notes, tblCollectionItemized.BookingActive, tblCollectionItemized.DepositReturned, tblTariff.Tariff
FROM tblTariff
INNER JOIN (
    tblProductions INNER JOIN (
        tblCollection INNER JOIN (
            tblEquipment 
            INNER JOIN tblCollectionItemized  ON tblEquipment.KitKey = tblCollectionItemized.KitKey
        ) ON tblCollection.HireID = tblCollectionItemized.HireID) 
    ON tblProductions.ProductionIDKey = tblCollection.ProductionName
) ON tblTariff.TariffKey = tblCollection.Tarriff
WHERE (
    tblCollectionItemized.BookingActive='TRUE'
    AND tblEquipment.PartOfKit IN (
        SELECT tblEquipment.KitRef
        FROM tblEquipment
        INNER JOIN tblCollectionItemized ON tblEquipment.KitKey = tblCollectionItemized.KitKey
        WHERE tblCollectionItemized.ReturnsNumber =43
    )
) 
OR (
    tblCollectionItemized.BookingActive='TRUE'
    AND tblCollectionItemized.ReturnsNumber =43
)

2 个答案:

答案 0 :(得分:0)

这里不是一个完整的答案,但是在逻辑顺序中使用一些别名和连接会使这个噩梦般的查询更容易看到正在发生的事情。

SELECT
    p.ProductionName
    , e.KitRef
    , e.PartOfKit
    , e.Description
    , c.HireID
    , c.CollectedBy
    , Format(c.DueBack,'dd/MM/yyyy') AS DueBack
    , Format(c.CollectionDate,'dd/MM/yyyy') AS CollectionDate
    , Format(c.CollectionTime,'HH:mm') AS CollectionTime
    , c.DiscountPC
    , ci.HireLine
    , ci.Notes
    , ci.BookingActive
    , ci.DepositReturned
    , t.Tariff

FROM tblTariff t
INNER JOIN tblCollection c ON t.TariffKey = c.Tarriff
INNER JOIN tblProductions p ON p.ProductionIDKey = c.ProductionName
INNER JOIN tblCollectionItemized ci ON c.HireID = ci.HireID
INNER JOIN tblEquipment e ON e.KitKey = ci.KitKey
WHERE ci.BookingActive = 'TRUE'
AND e.PartOfKit IN 
(
    SELECT e2.KitRef
    FROM tblEquipment e2
    INNER JOIN tblCollectionItemized ci2 ON e2.KitKey = ci2.KitKey
    WHERE ci2.ReturnsNumber = 43
) 
OR 
(
    ci.ReturnsNumber = 43
)

答案 1 :(得分:0)

您可以尝试使用EXISTS代替IN并向表格添加(nolock)提示

SELECT
    P.ProductionName, 
    E.KitRef, 
    E.PartOfKit, 
    E.Description, 
    C.HireID, 
    C.CollectedBy, 
    Format(C.DueBack,'dd/MM/yyyy') AS DueBack, 
    Format(C.CollectionDate,'dd/MM/yyyy') AS CollectionDate, 
    Format(C.CollectionTime,'HH:mm') AS CollectionTime, 
    C.DiscountPC, 
    CI.HireLine, 
    CI.Notes, 
    CI.BookingActive, 
    CI.DepositReturned, 
    T.Tariff
FROM tblTariff T
    INNER JOIN tblCollection C (nolock) ON T.TariffKey = C.Tarriff
    INNER JOIN tblProductions P (nolock) ON P.ProductionIDKey = C.ProductionName
    INNER JOIN tblCollectionItemized CI (nolock) ON C.HireID = CI.HireID
    INNER JOIN tblEquipment E (nolock) ON E.KitKey = CI.KitKey     
WHERE (
    tblCollectionItemized.BookingActive='TRUE'
    AND EXISTS (
        SELECT *
        FROM tblEquipment E2 (nolock)
        INNER JOIN tblCollectionItemized CI2 (nolock) ON E2.KitKey = CI2.KitKey
        WHERE CI2.ReturnsNumber =43 AND E.PartOfKit = E2.KitRef )

) 
OR (
    CI.BookingActive='TRUE'
    AND CI.ReturnsNumber =43
)