2011-01-14 18 views
11

Quando si uniscono due semplici tabelle su colonne di chiavi primarie e si pone una condizione di uguaglianza di addizione, ciò può essere fatto nella clausola join o where.È meglio fare un equi join nella clausola from o where clausola

Ad esempio, quanto segue è equivale. La mia domanda è - c'è qualche ragione per usare uno stile rispetto all'altro?

SELECT * 
FROM A 
INNER JOIN B ON A.A_ID = B.A_ID 
      AND A.DURATION = 3.00 

... vs:

SELECT * 
FROM A 
INNER JOIN B ON A.A_ID = B.A_ID 
WHERE A.DURATION = 3.00 
+2

suppongo per una query più complessa mantiene il join e le eventuali condizioni nello stesso luogo questo evitando lo scorrimento tra le parti della query – AJM

risposta

9

È una questione di stile. In generale, dovresti inserire le condizioni che definiscono la "forma" del set di risultati nella clausola FROM (cioè quelle che controllano quali righe di ogni tabella devono unire per produrre un risultato), mentre quelle condizioni che filtro il set di risultati dovrebbe essere nella clausola WHERE. Per INNER JOINs, gli effetti sono uguali, ma una volta coinvolti OUTER JOIN (LEFT, RIGHT), è molto più chiaro.


Nel tuo primo esempio, mi viene chiesto "cosa c'entra questo con la tabella B?" quando incontro questa strana condizione nel JOIN. Considerando che nel secondo, posso saltare la clausola FROM (e tutti i JOIN) se non sono interessato, e solo vedere le condizioni che determinano se le righe verranno restituite nella clausola WHERE.

1

La sua una questione di stile. L'ottimizzatore farà il meglio.

3

Per SQL Server 2000+, i piani di query per ciascuna di queste query saranno indentici e, quindi, anche le prestazioni.

È possibile verificare ciò utilizzando SSMS per visualizzare il piano di esecuzione effettivo per ciascuna query che colpisce CTRL + M prima dell'esecuzione della query. Il riquadro dei risultati avrà una scheda aggiuntiva che mostra il piano di esecuzione. Vedrai che in questo caso i due piani sono gli stessi.

6

È il tipo di JOIN che conta.
Non c'è differenza, entrambe le versioni della query fornite utilizzeranno lo stesso piano di esecuzione perché si tratta di un INNER JOIN.

Se si tratta di un outer join (IE: sinistra, destra), v'è una grande differenzatra le due versioni, perché i WHERE criteri vengono applicati dopo il join è fatto. Se i criteri sono specificati nella clausola ON, i criteri vengono applicati prima dello, in modo da ottenere una differenza considerevole tra i set di risultati.

10

In generale non fa alcuna differenza semantica.

C'è un caso limite in cui è possibile farlo. Se il costrutto (deprecato) GROUP BY ALL viene aggiunto alla query come illustrato di seguito.

DECLARE @A TABLE(A_ID INT, DURATION DECIMAL(3,2)) 
INSERT INTO @A VALUES(1,2.00) 

DECLARE @B TABLE(A_ID INT) 
INSERT INTO @B VALUES(1) 

/*Returns one row*/ 
SELECT * 
FROM @A A 
INNER JOIN @B B ON A.A_ID = B.A_ID 
WHERE A.DURATION = 3.00 
GROUP BY ALL A.A_ID, A.DURATION, B.A_ID 

/*Returns zero rows*/  
SELECT * 
FROM @A A 
INNER JOIN @B B ON A.A_ID = B.A_ID AND A.DURATION = 3.00 
GROUP BY ALL A.A_ID, A.DURATION, B.A_ID 
0
--Samples for time of join wheather can we write condition at where or ON 
create table #emp(id int ,teamid int) 
create table #team(tid int,name char(2)) 
insert into #emp values(1,1) 
insert into #emp values(2,1) 
insert into #emp values(3,2) 
insert into #emp values(4,0) 

insert into #team values(1,'A') 
insert into #team values(2,'B') 
insert into #team values(3,'C') 

--select * from #emp 
--select * from #team 

--on inner join => there is no difference in Query Exc. Plan 
--select * from #emp e join #team t on e.teamid=t.tid where e.teamid=2 
--select * from #emp e join #team t on e.teamid=t.tid and e.teamid=2 


/*on outetr join see the differnence If dealing with an OUTER JOIN (IE: LEFT, RIGHT), 
there is a huge difference between the two versions because the WHERE criteria is applied after the JOIN is made. 
If the criteria is specified in the ON clause, the criteria is applied before the JOIN is made which can made a considerable difference 
between the result sets.*/ 
select * from #emp e left join #team t on e.teamid=t.tid 
select * from #emp e left join #team t on e.teamid=t.tid where e.teamid=2 
select * from #emp e left join #team t on e.teamid=t.tid and (e.teamid=2 or t.tid=1) and t.name='A' 


drop table #emp 
drop table #team 
+0

si prega di leggere la spiegazione di seguito dettagliata che vi aiuta a grap le cose in fretta – Siva

+0

Non vedo una spiegazione.Solo una ripetizione di ciò che i Ponies di OMG hanno detto .. due anni fa. – Leigh