Bagaimana cara LEFT OUTER BERGABUNG menghasilkan lebih banyak catatan dari yang ada di tabel kiri?

165

Saya memiliki LEFT OUTER yang sangat mendasar, GABUNG untuk mengembalikan semua hasil dari tabel kiri dan beberapa informasi tambahan dari tabel yang jauh lebih besar. Tabel kiri berisi 4935 catatan namun ketika saya LEFT OUTER GABUNG ke tabel tambahan jumlah catatan secara signifikan lebih besar.

Sejauh yang saya ketahui, adalah mutlak bahwa LEFT OUTER JOIN akan mengembalikan semua catatan dari tabel kiri dengan catatan yang cocok dari tabel kanan dan nilai nol untuk setiap baris yang tidak dapat dicocokkan, dengan demikian adalah pemahaman saya bahwa seharusnya mustahil untuk mengembalikan lebih banyak baris daripada yang ada di tabel kiri, tetapi itu terjadi semua sama!

SQL Query mengikuti:

SELECT     SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM         SUSP.Susp_Visits LEFT OUTER JOIN
                      DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum

Mungkin saya telah membuat kesalahan dalam sintaksis atau pemahaman saya tentang LEFT OUTER JOIN tidak lengkap, semoga seseorang dapat menjelaskan bagaimana ini bisa terjadi?

Nota bene

Terima kasih atas jawaban yang bagus, pemahaman saya tentang LEFT OUTER JOINS sekarang jauh lebih baik, adakah yang bisa menyarankan cara query ini dapat dimodifikasi sehingga saya hanya mendapatkan sebanyak mungkin catatan yang ada di tabel sebelah kiri?

Permintaan ini murni untuk menghasilkan laporan dan kecocokan duplikat hanya membingungkan hal-hal.

/Nota bene

Jay Wilde
sumber
5
Untuk "mendapatkan sebanyak mungkin catatan yang ada di tabel sebelah kiri", Anda perlu menentukan baris mana dari sisi kanan untuk memilih jika ada beberapa kecocokan.
AK
1
bagaimana Anda menentukan ini? Saya ingin pertandingan pertama dikembalikan.
Simon Cross
1
Anda harus mendefinisikan apa yang dimaksud dengan pertandingan pertama. Apakah Anda ingin catatan paling awal, yang dengan id tertinggi atau apa?
HLGEM
1
Jika Anda cocok dengan kunci utama dalam tabel tambahan, pernyataan Anda sudah benar.
Prageeth godage
Saya sering menggunakan sumber daya seperti ini sebagai lembar contekan ketika membangun kueri. Jika tautannya pernah mati, cukup bergabung dengan google sql ; mereka adalah diagram Venn dari berbagai jenis gabung.
Zimano

Jawaban:

190

LEFT OUTER JOIN akan mengembalikan semua rekaman dari tabel LEFT yang tergabung dengan tabel RIGHT jika memungkinkan.

Namun, jika ada kecocokan, masih akan mengembalikan semua baris yang cocok, oleh karena itu, satu baris di LEFT yang cocok dengan dua baris dalam KANAN akan kembali sebagai dua ROW, sama seperti INNER JOIN.

EDIT: Sebagai tanggapan atas hasil edit Anda, saya baru saja melihat lebih jauh pada kueri Anda dan sepertinya Anda hanya mengembalikan data dari tabel LEFT. Oleh karena itu, jika Anda hanya ingin data dari tabel LEFT, dan Anda hanya ingin satu baris dikembalikan untuk setiap baris di tabel LEFT, maka Anda tidak perlu melakukan JOIN sama sekali dan hanya dapat melakukan SELECT langsung dari tabel LEFT.

Robin Day
sumber
1
Alasan bergabung ke meja sebelah kanan adalah jadi saya hanya mendapat catatan dari kiri di mana ada setidaknya satu catatan di meja sebelah kanan tetapi terima kasih banyak atas penjelasannya.
Jay Wilde
125
Table1                Table2
_______               _________
1                      2
2                      2
3                      5
4                      6

SELECT Table1.Id, Table2.Id FROM Table1 LEFT OUTER JOIN Table2 ON Table1.Id=Table2.Id

Hasil:

1,null
2,2
2,2
3,null
4,null
Andrew Lewis
sumber
1
Sangat sederhana, namun sangat kuat.
kiradotee
39

Bukan tidak mungkin. Jumlah catatan di tabel sebelah kiri adalah jumlah minimum catatan yang akan dikembalikan. Jika tabel kanan memiliki dua catatan yang cocok dengan satu catatan di tabel kiri, itu akan mengembalikan dua catatan.

HLGEM
sumber
12

Menanggapi naskah tambahan Anda, itu tergantung pada apa yang Anda inginkan.

Anda mendapatkan (mungkin) beberapa baris untuk setiap baris di tabel kiri Anda karena ada beberapa kecocokan untuk kondisi gabungan. Jika Anda ingin hasil total Anda memiliki jumlah baris yang sama dengan yang ada di bagian kiri kueri, Anda perlu memastikan bahwa kondisi gabungan Anda menyebabkan kecocokan 1-ke-1.

Atau, tergantung pada apa yang sebenarnya Anda inginkan, Anda dapat menggunakan fungsi agregat (jika misalnya Anda hanya menginginkan string dari bagian kanan, Anda dapat menghasilkan kolom yang merupakan string yang dibatasi koma dari hasil sisi kanan untuk baris kiri itu.

Jika Anda hanya melihat 1 atau 2 kolom dari gabungan luar, Anda mungkin mempertimbangkan untuk menggunakan subquery skalar karena Anda akan mendapatkan hasil 1 dijamin.

Chris Cameron-Mills
sumber
4
Ini adalah jawaban yang bagus karena menawarkan saran tentang cara mengembalikan hanya baris dari tabel kiri.
karns
9

Setiap catatan dari tabel kiri akan dikembalikan berkali-kali karena ada catatan yang cocok di tabel sebelah kanan - setidaknya 1, tetapi bisa dengan mudah lebih dari 1.

Alex Martelli
sumber
8

LEFT OUTER JOIN sama seperti INNER JOIN (gabung normal) akan mengembalikan sebanyak mungkin hasil untuk setiap baris di tabel kiri sebanyak pertandingan yang ditemukan di tabel kanan. Karenanya Anda dapat memiliki banyak hasil - hingga N x M, di mana N adalah jumlah baris di tabel kiri dan M adalah jumlah baris di tabel kanan.

Ini jumlah minimum hasil selalu dijamin dalam LEFT OUTER JOIN menjadi setidaknya N.

topchef
sumber
1
Saya mulai berpikir ketika jumlah baris sama dengan N x M dan satu-satunya situasi nyata yang muncul di benak saya adalah ketika N atau M sama dengan 1. Apakah Anda setuju?
BartoszMiller
2
Tidak, saya tidak. Anda tidak boleh menganggap syarat bergabung sebagai kunci kesetaraan saja. Ini bisa berupa kondisi yang berubah-ubah, misalnya rentang tanggal, ketidaksetaraan, dll. Dua kasus ekstrem: (a) N baris tidak memiliki satu kecocokan di antara baris M, lalu meninggalkan hasil gabungan luar di baris N yang cocok dengan NULL. (B) setiap baris N cocok dengan semua baris M, maka hasilnya adalah baris N x M ditetapkan.
topchef
1
Anda benar, saya berpikir tentang bergabung hanya dalam hal kesetaraan kunci. Saya suka contoh Anda dari "case b". Saya percaya bahwa "setiap baris N cocok dengan semua baris M" adalah resep umum ketika N x M baris dikembalikan, yang agak tidak mungkin untuk divisualisasikan ketika memikirkan kesetaraan kunci saja.
BartoszMiller
7

Mungkinkah itu hubungan satu ke banyak antara tabel kiri dan kanan?

Ken Burkhardt
sumber
6

Perhatikan jika Anda memiliki klausa di mana di tabel "sisi kanan 'dari kueri yang berisi gabungan luar kiri ... Jika Anda tidak memiliki catatan di sisi kanan yang memenuhi klausa where, maka catatan terkait dari' sisi kiri ' 'tabel tidak akan muncul di hasil permintaan Anda ....

Serge
sumber
1
Anda kemudian harus menambahkan kondisi ke klausa ON dari JOE LEFT OUTER yang sesuai.
Mik
6

Jika Anda membutuhkan sembarang baris dari sisi kanan

SELECT SuspReason, SiteID FROM(
    SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER()
    OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn
    FROM SUSP.Susp_Visits
    LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
) AS t
WHERE rn=1

atau hanya

SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM SUSP.Susp_Visits WHERE EXISTS(
    SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
)
AK
sumber
1
Karena Anda tidak memberikan DDL dan DML, saya tidak menguji. Ngomong-ngomong aku berpikir bahwa EXIS adalah yang kamu inginkan. Coba ini: SELECT SuspReason, SiteID FROM (SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER () LEBIH (PARTISI DENGAN SUSP.Susp_Visits.SiteID PESAN DENGAN SUSP.SUSP_VisitsSITRUSSPUTRITSUSSPUTUSSUSSPUTUSKETERBantuan. GABUNG DATA.Dim_Member TENTANG SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum) SEBAGAI DI MANA rn = 1
AK
2

Sepertinya ada beberapa baris dalam tabel DATA.Dim_Member per baris SUSP.Susp_Visits.

bdukes
sumber
2

jika beberapa (x) baris di Dim_Member dikaitkan dengan satu baris di Susp_Visits, akan ada x baris di set hasil.

Manu
sumber