2014-10-28 27 views
5

Co jest nie tak z tym prostym łączeniem zewnętrznym SQL?W jaki sposób A lewe sprzężenie zewnętrzne B może zwrócić więcej wierszy niż w A?

select count(*) from A -- 25766 
select count(*) from B -- 1242 
select count(*) from A left outer join B on A.b = B.b -- 310176 

zwraca odpowiednio 25766, 1242 i 310176 wierszy. (To jest dla Microsoft SQL Server 2012.) W jaki sposób A left outer join B może kiedykolwiek zwrócić więcej wierszy niż istnieje w A, szczególnie biorąc pod uwagę diagram Venna this? Chyba popełniam głupi błąd, ale co to jest?

+2

Może być tak, że kolumny b nie jest całym kluczem? – Jens

+0

+1 Sprawdzę. Jak to wyjaśnić 310176? – Drux

+2

Jeśli b jest tylko częścią klucza, może to być jedna linia w odwołaniu A o wiele więcej linii w B i jeśli w twoim przykładzie 1 rekord A odniesienia 12,0 ... wiersze w B otrzymasz swój wynik. – Jens

Odpowiedz

14

Może się to zdarzyć, gdy kolumna b nie jest unikatowa w tabeli B. Załóżmy, że masz te dane:

 
    A  B 
+---+ +---+---+ 
| b | | b | c | 
+---+ +---+---+ 
| 1 | | 2 | 1 | 
| 2 | | 2 | 2 | 
+---+ +---+---+ 

Po lewej przyłączenia od A do B na kolumnie b, masz

 
+-----+------+------+ 
| A.b | B.b | B.c | 
+-----+------+------+ 
| 1 | NULL | NULL | 
| 2 | 2 | 1 | 
| 2 | 2 | 2 | 
+-----+------+------+ 

co daje trzy wiersze w sumie, chociaż zarówno A i B tylko po dwa rzędy.

+0

+1 Tak, 'wybierz liczbę (różne b) z B' zwraca 197 i 197 << 1242. – Drux

3

Nie ma w tym nic dziwnego (i ta sytuacja dotyczy również wewnętrznych połączeń). Lewy sprzężenie zewnętrzne:

  • zwraca wszystkie wiersze z przekroju B, gdzie warunki złączenia mecz
  • i zwraca wszystkie wiersze z którym łączą warunek nie pasuje

Więc na minimum zapytaniu zwróci 25766 wierszy, ale może być ich więcej. Jest możliwe, że jeden wiersz w tabeli A, który odpowiada wielu rzędów w tabeli B. Przykład:

A    B    Result 
+----+----+ +-----+----+ +------+-----+-----+------+ 
| id| b| | id| b| | a.id| a.b| b.b| b.id| 
+----+----+ +-----+----+ +------+-----+-----+------+ 
| 1| 10| | 123| 10| |  1| 10| 10| 123| 
+----+----+ | 456| 10| |  1| 10| 10| 456| 
      +-----+----+ +------+-----+-----+------+ 

to zwraca dwa rzędy, nawet jeśli nie ma jeden wiersz w tabeli A.