2016-08-03 16 views
1

Die fragliche Aussage funktioniert richtig, ich muss nur verstehen, warum und wie!JOIN Unterselektionsbereich in ON Bedingung? (Warum und Verhaltensvorteile?)

Ich habe die folgende Syntax in einer Anweisung gefunden, die Informationen für die Mitarbeiteranalyse erhält.

Nie so etwas gesehen und kann nichts über das Verhalten mit Google finden. Ich hoffe, Sie können mir helfen zu verstehen, wie das funktioniert und wie man es benutzt.

Tabelle 1 Mitarbeiter (EmployeeID, Name, Geburtstag, ...)

Tabelle 2 Contracts (ContractID, EmployeeID, Startdatum, Enddatum, ...)

Tabelle 3 Zeit -Modelle (TimeID, ContractID, EmployeeID, MonthlyDate, ...)

Tabelle 4 Versicherung (InsuranceID, ContractID, EmployeeID, Jobtype, ...)

Der subselect im Code später Ausgänge:

Columname MonthlyDate 
Values('2016-02-01 00:00:00.000', 
'2016-04-01 00:00:00.000', 
'2016-01-01 00:00:00.000', 
'2016-03-01 00:00:00.000', 
'2016-06-01 00:00:00.000', 
'2016-05-01 00:00:00.000', 
'2016-07-01 00:00:00.000') 

Die SQL in Frage wie folgt aussieht:

SELECT E.EmployeeID+C.ContractID, D.Date, E.Name 

FROM Employees AS E 

LEFT OUTER JOIN Contract AS C ON E.EmployeeID = C.Employee ID 

--This is where the SQL I was talking about starts 
LEFT OUTER JOIN (
    SELECT MonthlyDate 
    FROM Time-models 
    WHERE MonthlyDate >= Convert(DATETIME, '2016-01-01', 102)) AS D 
ON (D.MonthlyDate >= C.ContractStartDate AND D.MonthlyDate <= C.ContractEndDate) 
/*I can not explain this On-Condition*/ 

LEFT OUTER JOIN Insurance as I 
ON (I.EmployeeID = E.EmployeeID AND I.ContractID = C.ContractID) 

WHERE I.JobType = 'Clerk' 
AND (I.InsuranceStartDate <= D.MonthlyDate AND I.InsuranceEndDate >= D.MonthlyDate) 
/* I can not understand which compare values are used in D.MonthlyDate 
because of the the vague ON-Condition */ 
+3

Wenn 'LEFT JOIN', setzen Sie die Bedingungen der rechten Seitentabelle in die 'ON'-Klausel, um echtes linkes Join-Verhalten zu erhalten! (Wenn Sie in WHERE sind, erhalten Sie regelmäßige innere Join-Ergebnisse.) wechsle zuletzt WHERE zu UND in deiner Anfrage! – jarlh

+0

Vielen Dank für Ihre Antwort! Ich verstehe das. Die Sache ist in der zweiten Verbindung gibt es keine Gleichheit, um IDs zuzuweisen, wie es normalerweise getan wird, stattdessen gibt es einen Bereich. – Blufftl

+0

Was ist vage an der ON-Bedingung für die Unterabfrage? Für die Zwecke hier, denken Sie nicht an die Unterabfrage als etwas anderes als eine andere Tabelle.Die ON-Bedingungen funktionieren genau so wie Ihre anderen 'JOIN's. – iamdave

Antwort

1

Der WHERE Zustand Ihrer Abfrage wird die LEFT JOIN in eine INNER JOIN drehen. (Wenn eine Zeile nicht, dann passt die I Spalten NULL und nicht sein, die WHERE Bedingungen.)

Zusätzlich:

  • Sie die Unterabfrage überhaupt nicht brauchen.
  • SQL Server erkennt Daten im Format YYYYMMDD und fast immer im Format YYYY-MM-DD ohne Konvertierung.

So könnten Sie auch neu schreiben die Abfrage wie:

SELECT E.EmployeeID+C.ContractID, D.Date, E.Name 
FROM Employees E JOIN 
    Contract C 
    ON E.EmployeeID = C.Employee ID JOI 
    [Time-models] d 
    ON D.MonthlyDate >= C.ContractStartDate AND 
     D.MonthlyDate <= C.ContractEndDate AND 
     MonthlyDate >= '2016-01-01' JOIN 
    Insurance as I 
    ON I.EmployeeID = E.EmployeeID AND 
     I.ContractID = C.ContractID 
WHERE I.JobType = 'Clerk' AND 
     I.InsuranceStartDate <= D.MonthlyDate AND 
     I.InsuranceEndDate >= D.MonthlyDate; 

Ich bin nicht sicher, ob dies Ihre Frage beantwortet, though.

+1

Das war eine großartige Antwort und half tatsächlich alles noch besser zu verstehen! Vielen Dank! – Blufftl

0

"Ich verstehe nicht, wie ein einzelner Wert zugeordnet werden kann." Nein, dies entspricht offensichtlich einer Reihe von Zeilen, keine einzige. Betrachten Sie dieses einfache Beispiel

select * 
from (
    values 
    (1, cast('2016-02-02' as date), cast('2016-03-02' as date)) 
    ,(2, cast('2016-02-02' as date), cast('2016-05-02' as date)) 
    ,(3, cast('2016-02-02' as date), cast('2016-02-04' as date)) 
    ) C(id,ContractStartDate, ContractEndDate) 
left join ( 
    values 
    ('2016-02-01') 
    ,('2016-04-01') 
    ,('2016-01-01') 
    ,('2016-03-01') 
    ,('2016-06-01') 
    ,('2016-05-01') 
    ,('2016-07-01') 
    ) D(MonthlyDate) 
    on D.MonthlyDate >= C.ContractStartDate AND D.MonthlyDate <= C.ContractEndDate 
; 

Die Abfrage 1 bis 3 Reihen von D für jede C Reihe zurück.

+0

Vielen Dank das hilft mir sehr! – Blufftl