2017-01-23 5 views
0

Учитывая следующий запрос:Оптимизация запросов: Стыковка в подзапросе

SELECT [CustomerID], [CustomerName],[CustomerAddress],[CustomerPhone] 
FROM Customers 
WHERE CustomerID IN 
    (SELECT CustomerID FROM Buys b 
    JOIN CarService cs ON cs.SoldCarNum=b.SoldCarNum   
    JOIN GarageWorkers gw ON cs.WorkerNum=gw.WorkerNum 
    WHERE YEAR(cs.ServiceDate) BETWEEN 2015 AND 2016 
    GROUP BY CustomerID 
    HAVING COUNT(DISTINCT gw.GarageID)>= 7) 

Есть ли возможный способ сделать его более эффективным? Мне не нравятся ПРИСОЕДИНИКИ, но я не вижу, как я могу избавиться от них.

Edit:

Я использую Microsoft SQL Server.

+0

Какая СУБД вы используете? –

ответ

1

Я предполагаю, что это ваш запрос:

SELECT [CustomerID], [CustomerName], [CustomerAddress], [CustomerPhone] 
FROM Customers c 
WHERE c.CustomerID IN (SELECT b.CustomerID 
         FROM Buys b JOIN 
          CarService cs 
          ON cs.SoldCarNum = b.SoldCarNum JOIN  
          GarageWorkers gw 
          ON cs.WorkerNum = gw.WorkerNum 
         WHERE YEAR(cs.ServiceDate) BETWEEN 2015 AND 2016 
         GROUP BY CustomerID 
         HAVING COUNT(DISTINCT gw.GarageID) >= 7 
        ); 

Это, казалось бы, клиенты, которые имели семь или больше автомобилей обслуживать свой автомобиль в 2015 году и 2016 году Во-первых, я хотел бы изменить сравнение даты использования реальные даты, а не YEAR() (поэтому можно использовать индексы). Это выглядит так:

SELECT [CustomerID], [CustomerName], [CustomerAddress], [CustomerPhone] 
FROM Customers c 
WHERE c.CustomerID IN (SELECT b.CustomerID 
         FROM Buys b JOIN 
          CarService cs 
          ON cs.SoldCarNum = b.SoldCarNum JOIN  
          GarageWorkers gw 
          ON cs.WorkerNum = gw.WorkerNum 
         WHERE cs.ServiceDate >= '2015-01-01' AND 
          cs.ServiceDate < '2017-01-01' 
         GROUP BY b.CustomerID 
         HAVING COUNT(DISTINCT gw.GarageID) >= 7 
        ); 

Далее вы хотите индексы. Я бы рекомендовал:

  • CarService(ServiceDate, SoldCarNum, WorkerNum)
  • Buys(SoldCarNum, CustomerId)
  • GarageWorkers(WorkerNum, GarageID)

Эти индексы "крышка" подзапрос, а это означает, что у них есть все столбцы в подзапроса.

Вы не упомянули базу данных. В некоторых базах данных замена IN (<subquery>) на JOIN (<subquery>) также часто повышала бы производительность.

+0

Спасибо. Я использую Microsoft SQL Server. Это дает вам больше идей о том, как улучшить запрос? – Alon

+0

В моем случае (MSSQL) поможет JOIN ()? – Alon

+0

@Alon. , , Я на самом деле не уверен, но я бы написал его как 'JOIN', а не' IN', только потому, что он более оптимизирован в большем количестве баз данных. –