thongkorn โพสต์ 2017-11-6 13:03:08

[VB.NET] พื้นฐานของ SQL Joins ระหว่างตารางข้อมูล 2 ตาราง

http://www.g2gnet.com/webboard/images/vbnet/DBVBJoin.png
ในบทความนี้ แอดมินจะจำลอง เพื่อแสดงให้เห็นถึงการจอย (JOIN) หรือเชื่อมความสัมพันธ์ระหว่างตารางข้อมูล 2 ตารางเข้าหากัน ด้วยวิธีการกระจายข้อมูลออกให้เห็นในรูปแบบของเซ็ต (SET) โดยใช้ไฟล์ฐานข้อมูล Microsoft Access มาเป็นตัวอย่าง ซึ่งมันก็ใช้ไวยากรณ์ที่คล้ายๆกันฐานข้อมูลตัวอื่นๆนั่นแหละครับท่านผู้ชม ...
http://www.g2gnet.com/webboard/images/vbnet/dbtable.png
สมมุติชื่อเล่นตาราง A คือ ตารางนักศึกษา (Student)
สมมุติชื่อเล่นตาราง B คือ ตารางอาจารย์ที่ปรึกษา (Advisor)
ในการแจกแจงสมาชิกท่านต้องกลับไปเปิดจากคณิตศาสตร์ ม.4 เทอม 1 ดูกันเองครับ ... สรุปให้สั้นๆ คือ ...
- Student 1 และ 9 มี Advisor 1 เป็นที่ปรึกษา ส่วน Student 5, 7, และ 10 มีอาจารย์ Advisor 3 เป็นที่ปรึกษา
- Student 2 และ 4 ไม่มีความสัมพันธ์ของตารางข้อมูลกับอาจารย์ที่ปรึกษาคนใด และ Advisor 5 ก็ไม่ได้เป็นที่ปรึกษาให้แก่นักศึกษาคนใด พวกนี้จัดว่าอยู่นอกเหนือความสัมพันธ์กัน
หมายเหตุ: AdvisorFK คือคีย์รองจากตาราง Student (เพราะคีย์หลักตารางนี้คือ StudentPK) ที่เชื่อมกลับไปหาคีย์หลัก AdvisorPK ซึ่งความหมายก็คือตัวเดียวกันนั่นแหละครับ
กรณี Inner Join (หรือ อินเตอร์เซคชัน Intersection) ...
http://www.g2gnet.com/webboard/images/vbnet/DBInner.png
พบว่าตาราง A และ B หากมีความสัมพันธ์กันแบบไร้เงื่อนไขก็จะมีสมาชิกอยู่ 5 รายการ ซึ่งกรณีของ Inner Join นี้เราต้องใช้งานบ่อยมากSELECT Student.StudentPK, Student.StudentName, Advisor.AdvisorName
FROM Student INNER JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK
ORDER BY Student.StudentPKตาราง A JOIN กับตาราง B เมื่อคีย์รอง AdvisorFK มีค่าเท่ากับคีย์หลัก AdvisorPK
http://www.g2gnet.com/webboard/images/vbnet/VBInner.png
ความหมายคือ รายชื่อของนักศึกษาที่มีอาจารย์เป็นที่ปรึกษาเรียบร้อย

กรณี Left Join ...
http://www.g2gnet.com/webboard/images/vbnet/DBLeft.png
ประกอบไปด้วยสมาชิก 7 รายการ
SELECT Student.StudentPK, Student.StudentName, Advisor.AdvisorName
FROM Student LEFT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK
ORDER BY Student.StudentPKhttp://www.g2gnet.com/webboard/images/vbnet/VBLeft.png
Student 2 ต้องให้ Advisor 8 เป็นที่ปรึกษา แต่ทว่า Advisor 8 ไม่มีรายชื่อปรากฏอยู่ในตาราง Advisor (กรณี Student 4 ก็เหมือนกัน คือมี Advisor 2 เป็นที่ปรึกษา แต่ที่ปรึกษาไม่ได้อยู่ในตาราง Advisor)

กรณี Right Join ...
http://www.g2gnet.com/webboard/images/vbnet/DBRight.png
ประกอบด้วยสมาชิก 6 รายการ
SELECT Student.StudentPK, Student.StudentName, Advisor.AdvisorName
FROM Student RIGHT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK
ORDER BY Student.StudentNamehttp://www.g2gnet.com/webboard/images/vbnet/VBRight.png
หมายความว่า Advisor 5 ยังไม่ได้เป็นที่ปรึกษาให้นักศึกษาคนใดๆเลย

ทั้งสองตาราง หากมาทำ Union หรือ Full Outer Join กัน
http://www.g2gnet.com/webboard/images/vbnet/DBFull.png
ก็จะมีสมาชิกทั้งหมด 8 รายการ อ้าววว ทำไมไม่ใช่ 10 ล่ะ ... ก็เพราะว่ามันมีความสัมพันธ์กันอยู่ 5 รายการ และไม่เกี่ยวข้องกันทางซ้าย 2 รายการ และไม่เกี่ยวข้องกันทางขวา 1 รายการ เลยรวมได้แค่ 8 รายการนั่นเอง
SELECT Student.StudentPK, Student.StudentName, Student.AdvisorFK, Advisor.AdvisorPK
FROM Student LEFT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK
UNION http://www.g2gnet.com/webboard/images/vbnet/VBFull.png
กรณีของ MS Access จะไม่มีคำสั่ง SQL ในการ Full Outer Join เราแก้ปัญหานี้ด้วยการใช้ LEFT และ RIGHT มารวมกันแทนครับผม

โค้ด VB.NET เพื่อช่วยในการเรียนรู้และเสริมสร้างความเข้าใจ ...
Imports System.Data.OleDb

Public Class frmJoinDBMethod
    Dim Conn As OleDbConnection

    ' / --------------------------------------------------------------------------------
    ' / FIRST : Connect MS Access DataBase
    Public Function ConnectDataBase() As System.Data.OleDb.OleDbConnection
      Dim strPath As String = Application.StartupPath.ToLower
      '// MS Access 2007+ DB at data folder.
      strPath = strPath.Replace("\bin\debug", "\data").Replace("\bin\release", "\data").Replace("\bin\x86\debug", "\data")
      If Microsoft.VisualBasic.Right(strPath, 1) <> "\" Then strPath = strPath + "\"
      Try
            '//
            Dim strConn As String = _
                "Provider = Microsoft.ACE.OLEDB.12.0;"
            strConn += _
                "Data Source = " & strPath & "SampleJoin.accdb"

            Conn = New OleDb.OleDbConnection(strConn)
            '// Connection (Conn)
            Conn.ConnectionString = strConn
            '// Return Connection
            Return Conn
      Catch ex As Exception
            MessageBox.Show(ex.Message)
            Conn = Nothing
            Return Conn
      End Try
    End Function

    Private Sub frmLeftRightInnerJoin_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      Me.CenterToScreen()
      ' / --------------------------------------------------------------------------------
      ' Setup DataGridView @Run Time
      With dgvData
            .RowHeadersVisible = False
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .AllowUserToResizeRows = False
            .MultiSelect = False
            .SelectionMode = DataGridViewSelectionMode.FullRowSelect
            .ReadOnly = True
            .Font = New Font("Tahoma", 9)
            ' Header style
            With .ColumnHeadersDefaultCellStyle
                .BackColor = Color.Navy
                .ForeColor = Color.White
                .Font = New Font(dgvData.Font, FontStyle.Bold)
            End With
            '// Auto adjust columns size.
            dgvData.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            dgvData.AutoResizeColumns()
      End With
      '//
      Conn = ConnectDataBase()
      lblRecordCount.Text = ""
    End Sub

    ' / --------------------------------------------------------------------------------
    ' / Sub Program to show Inner, Left and Right Join
    Private Sub RetrieveData(Optional ByVal JoinType As Byte = 0)
      Dim strSQL As String
      '// 0 = Inner, 1 = Left and 2 = Right Join, 3 = Union
      Select Case JoinType
            '// INNER JOIN
            Case 0
                strSQL = _
                  " SELECT Student.StudentPK, Student.StudentName, Advisor.AdvisorName " & _
                  " FROM Student INNER JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK " & _
                  " ORDER BY Student.StudentPK "

                '// LEFT JOIN
            Case 1
                strSQL = _
                  " SELECT Student.StudentPK, Student.StudentName, Advisor.AdvisorName " & _
                  " FROM Student LEFT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK " & _
                  " ORDER BY Student.StudentPK "

                '// RIGHT JOIN
            Case 2
                strSQL = _
                  " SELECT Student.StudentPK, Student.StudentName, Advisor.AdvisorName " & _
                  " FROM Student RIGHT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK " & _
                  " ORDER BY Student.StudentName "

                '// UNION
            Case 3
                strSQL = _
                  " SELECT Student.StudentPK, Student.StudentName, Student.AdvisorFK, Advisor.AdvisorPK " & _
                  " FROM Student LEFT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK " & _
                  " UNION " & _
                  " SELECT Student.StudentPK, Student.StudentName, Student.AdvisorFK, Advisor.AdvisorPK " & _
                  " FROM Student RIGHT JOIN Advisor ON Student.AdvisorFK = Advisor.AdvisorPK "
                '" FROM Advisor LEFT JOIN Student ON Advisor.AdvisorPK = Student.AdvisorFK "

      End Select
      '// Start
      Try
            If Conn.State = ConnectionState.Closed Then Conn.Open()
            Dim Cmd As New OleDb.OleDbCommand(strSQL, Conn)
            Dim Reader As OleDb.OleDbDataReader = Cmd.ExecuteReader
            Dim DT As DataTable = New DataTable
            DT.Load(Reader)
            dgvData.DataSource = DT
            DT.Dispose()
      Catch ex As Exception
            MessageBox.Show(ex.Message)
      End Try
      '//
      lblRecordCount.Text = ""
    End Sub

    '// INNER
    Private Sub itemInner_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles itemInner.Click
      Call RetrieveData(0)
    End Sub

    '// LEFT
    Private Sub itemLeft_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles itemLeft.Click
      Call RetrieveData(1)
    End Sub

    '// RIGHT
    Private Sub itemRight_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles itemRight.Click
      Call RetrieveData(2)
    End Sub

    '// UNION
    Private Sub itemFull_Click(sender As System.Object, e As System.EventArgs) Handles itemFull.Click
      Call RetrieveData(3)
    End Sub

    Private Sub itemClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles itemClose.Click
      Me.Close()
    End Sub

    Private Sub frmLeftRightInnerJoin_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
      If Conn.State = ConnectionState.Open Then Conn.Close()
      Me.Dispose()
      Application.Exit()
    End Sub

End Classดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่

g2gsoftuser โพสต์ 2022-10-25 18:54:27

ขอบคุณครับ

MMEE007 โพสต์ 2022-12-11 21:10:51

ขอบพระคุณคัพ อาจารย์ :loveliness::loveliness:

thawatchai-sena โพสต์ 2023-9-12 12:15:38

ขอบคุณครับ
หน้า: [1]
ดูในรูปแบบกติ: [VB.NET] พื้นฐานของ SQL Joins ระหว่างตารางข้อมูล 2 ตาราง