2012-11-21 8 views
5

natknąłem się tego zapytania T-SQL utworzone w programie SQL Server 2005 bazy danych:Co to znaczy mieć kilka klauzul z sprzężenia wewnętrzne wraz

Select s_bs.ScheduleHeaderId, 
     s_bs.ScheduleBatchScheduleId, 
     FlowRateOperational.FlowRate, 
     BatchScheduleFlowRateOperational.EffectiveStartTime, 
     BatchScheduleFlowRateOperational.EffectiveEndTime 
From BatchSchedule as bs 
Inner Join ConnectionPoint as cp on bs.ConnectionPointId = cp.ConnectionPointId 
Inner Join ScheduleBatch as s_b 
Inner Join ScheduleConnectionPoint as s_cp 
Inner Join ScheduleBatchSchedule as s_bs 
      on s_cp.ScheduleConnectionPointId = s_bs.ScheduleConnectionPointId 
      on s_b.ScheduleBatchId = s_bs.ScheduleBatchId 
      on cp.ConnectionPointName = s_cp.ConnectionPointName and bs.BatchID = s_b.BatchID 
Inner Join BatchScheduleFlowRateOperational on bs.BatchScheduleId = BatchScheduleFlowRateOperational.BatchScheduleId 
Inner Join FlowRateOperational on BatchScheduleFlowRateOperational.FlowRateOperationalId = FlowRateOperational.FlowRateOperationalId 

Nie jestem ekspertem SQL za daleko, ale przynajmniej Myślę, że wiem, jak dołączyć do tabel i nigdy wcześniej nie widziałem takiego sposobu łączenia tabel.

Czy ma kilka klauzul ON razem po ich JOINS produkujących różne wyniki lub zwiększenie wydajności?

Dlaczego ta osoba nie mogła po prostu przesunąć złączeń i zachować klauzule ON obok odpowiadającego im JOIN?

Dzięki za każdym świetle można przelał na tej „tajemnicy” :)

+0

Kto wiedział, że to możliwe ?! Nie zrobiłem tego. – usr

+0

Czy to działa? – codingbiz

+0

... W jakich okolicznościach * jest * to możliwe? Nie mogę odtworzyć tego zachowania - jest to błąd składniowy. –

Odpowiedz

1

Klauzula ON może być umieszczony bezpośrednio po każdym INNER JOIN (który wygląda ładniej do mnie). Ale czasami jest nieuniknione umieszczanie klauzul ON dla pierwszych kilku złączeń po późniejszym złączeniu.Na przykład tabela, która zapewnia sprzężenie stan nie jest jeszcze dostępna w łańcuchu JOIN, na przykład:

SELECT * FROM 
A INNER JOIN 
B INNER JOIN 
C 
    ON B.Col1 = C.Col1 
    ON A.Col2 = C.Col2 

Look, że oba ON klauzule odnoszące się do C tak powiązany ON klauzula nie może pojawić się wcześniej. Można temu zapobiec, umieszczając najpierw C, ale w zależności od zastosowania może być ona mniej czytelna.

Powyższe jest tylko z punktu widzenia składni. Powinny też istnieć pewne względy wydajności, których nie jestem świadomy.

+0

Byłbym bardzo zainteresowany wiedzą, w jaki sposób ta składnia może poprawić wydajność. Jeśli mógłbyś podać dodatkowe wyjaśnienie, przykład i/lub kilka dalszych linków do czytania, byłoby to bardzo cenne. –

0

po prostu brzydki pisemnej Jestem pewien, że tak samo jak:

Select s_bs.ScheduleHeaderId, 
     s_bs.ScheduleBatchScheduleId, 
     FlowRateOperational.FlowRate, 
     BatchScheduleFlowRateOperational.EffectiveStartTime, 
     BatchScheduleFlowRateOperational.EffectiveEndTime 
From BatchSchedule as bs 
Inner Join ConnectionPoint as cp on bs.ConnectionPointId = cp.ConnectionPointId 
Inner Join ScheduleBatch as s_b on s_b.BatchID = bs.BatchID 
Inner Join ScheduleBatchSchedule as s_bs on s_b.ScheduleBatchId = s_bs.ScheduleBatchId 
Inner Join ScheduleConnectionPoint as s_cp on s_cp.ScheduleConnectionPointId = s_bs.ScheduleConnectionPointId and s_cp.ConnectionPointName = cp.ConnectionPointName 
Inner Join BatchScheduleFlowRateOperational on bs.BatchScheduleId = BatchScheduleFlowRateOperational.BatchScheduleId 
Inner Join FlowRateOperational on BatchScheduleFlowRateOperational.FlowRateOperationalId = FlowRateOperational.FlowRateOperationalId 
1

to nie jest odpowiedzią , po prostu zmienił położenie warunków (myślę)

Select s_bs.ScheduleHeaderId, 
     s_bs.ScheduleBatchScheduleId, 
     f.FlowRate, 
     b.EffectiveStartTime, 
     b.EffectiveEndTime 
From 

BatchSchedule as bs Inner Join 

ConnectionPoint as cp on 
    cp.ConnectionPointId=bs.ConnectionPointId Inner Join 

ScheduleBatch as s_b on 
s_b.BatchID=bs.BatchID Inner Join 

ScheduleConnectionPoint as s_cp on 
    s_cp.ConnectionPointName=cp.ConnectionPointName Inner Join 

ScheduleBatchSchedule as s_bs on 
    s_bs.ScheduleConnectionPointId = s_cp.ScheduleConnectionPointId Inner Join 

BatchScheduleFlowRateOperational b on 
b.BatchScheduleId = bs.BatchScheduleId Inner Join 

FlowRateOperational f on 
f.FlowRateOperationalId=b.FlowRateOperationalId 

where 
s_bs.ScheduleBatchId = s_b.ScheduleBatchId 

czy można postawić warunek where w instrukcji and po inner joining s_bs, ale myślę, że wyróżnia się bardziej, jeśli jest poza łańcuchem.

1

Nie ma znaczenia dla połączeń wewnętrznych, ale oczywiście przyniesie zupełnie inne wyniki dla innych rodzajów połączeń.

Jako przykładowy przykład, a LEFT JOIN (b CROSS JOIN c) ON b.a = a.a AND c.a = a.a zwraca tylko niepuste wiersze jednocześnie dla obu tabel b i c, ale a LEFT JOIN b ON b.a = a.a LEFT JOIN c ON c.a = a.a oceni niezależnie zdania.

+0

To naprawdę robi ogromną różnicę w wydajności !!! –

2

Gdy masz tylko wewnętrzne połączenia, kolejność łączenia nie ma znaczenia. Zestawy wyników są takie same. Dwie poniższe wersje są równoważne.

Wspólna sposób łączenia:

FROM 
    tableA AS a 
    JOIN 
    tableB AS b 
     ON b.aid = a.aid 
    JOIN 
    tableC AS c 
     ON c.bid = b.bid 

A nie tak często (zauważyć nawiasy są tam tylko dla jasności pierwszeństwa, mogą zostać usunięte bezpiecznie, jak w zapytaniu):

FROM 
    tableA AS a 
    JOIN 
     ( tableB AS b 
     JOIN 
      tableC AS c 
      ON c.bid = b.bid 
    ) 
    ON b.aid = a.aid 

Kiedy masz sprzężenia zewnętrzne chociaż (LEFT, RIGHT lub FULL), sytuacja jest inna. Jeśli zastąpisz JOIN z LEFT JOIN w powyższych zapytaniach, to one nie są równoważne i mogą generować różne zestawy wyników.

Nawet jeden z (wielu) łączy sprawy. Poniższe dwa nie są równoważne:

FROM 
    tableA AS a 
    LEFT JOIN 
    tableB AS b 
     ON b.aid = a.aid 
    JOIN 
    tableC AS c 
     ON c.bid = b.bid 

FROM 
    tableA AS a 
    LEFT JOIN 
      tableB AS b 
     JOIN 
      tableC AS c 
      ON c.bid = b.bid 

    ON b.aid = a.aid