2017-01-23 5 views
0

Bei der folgenden Abfrage:Abfrageoptimierung: JOIN in subquery

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) 

Gibt es eine Möglichkeit, es effizienter zu machen? Ich mag die JOINs nicht, aber ich sehe nicht, wie ich sie loswerden kann.

Edit:

Ich verwende Microsoft SQL Server.

+0

Welche DBMS verwenden Sie? –

Antwort

1

ich, dass dies bin zu raten ist, Ihre Abfrage:

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 
        ); 

Dies scheint Kunden zu sein, die sieben oder mehr hatten Autos ihr Auto im Jahr 2015 und 2016. Der erste Dienst, würde ich das Datum ändern Vergleich zu verwenden, Echtdaten statt YEAR() (so können Indizes verwendet werden). Das sieht so aus:

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 
        ); 

Als nächstes wollen Sie Indizes. Ich würde empfehlen:

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

Diese Indizes "Deckel" die Unterabfrage, was bedeutet, dass sie alle Spalten in der Unterabfrage haben.

Sie erwähnen die Datenbank nicht. In einigen Datenbanken würde das Ersetzen der IN (<subquery>) durch JOIN (<subquery>) oft auch die Leistung verbessern.

+0

Danke. Ich benutze Microsoft SQL Server. Gibt das Ihnen weitere Ideen, wie Sie die Abfrage verbessern können? – Alon

+0

In meinem Fall (MSSQL) würde der JOIN () helfen? – Alon

+0

@Alon. . . Ich bin mir eigentlich nicht sicher, aber ich würde es als 'JOIN' anstelle von' IN' schreiben, nur weil es eher in mehr Datenbanken optimiert wird. –