HOW TO:使用 Joins 以 LINQ 合併資料 (Visual Basic)

更新:2007 年 11 月

Visual Basic 提供 Join 和 Group Join 查詢子句,可以讓您根據集合之間的共同值合併多個集合的內容。這些值又稱為「索引鍵」(Key) 值。熟悉關聯式資料庫概念的開發人員會發現,Join 子句就是 INNER JOIN,而 Group Join 子句其實就是 LEFT OUTER JOIN。

本主題中的範例會示範幾個使用 Join 和 Group Join 查詢子句來合併資料的方法。

建立專案和加入範例資料

若要建立含有範例資料和型別的專案

  1. 若要執行本主題中的範例,請開啟 Visual Studio 並加入新的 Visual Basic 主控台應用程式專案。按兩下 Visual Basic 建立的 Module1.vb 檔案。

  2. 本主題中的範例使用 Person 和 Pet 型別,以及下列程式碼範例中的資料。請將這個程式碼複製至 Visual Basic 建立的預設 Module1 模組中。

    Private _people As List(Of Person)
    Private _pets As List(Of Pet)
    
    Function GetPeople() As List(Of Person)
      If _people Is Nothing Then CreateLists()
      Return _people
    End Function
    
    Function GetPets(ByVal people As List(Of Person)) As List(Of Pet)
      If _pets Is Nothing Then CreateLists()
      Return _pets
    End Function
    
    Private Sub CreateLists()
      Dim pers As Person
    
      _people = New List(Of Person)
      _pets = New List(Of Pet)
    
      pers = New Person With {.FirstName = "Magnus", .LastName = "Hedlund"}
      _people.Add(pers)
      _pets.Add(New Pet With {.Name = "Daisy", .Owner = pers})
    
      pers = New Person With {.FirstName = "Terry", .LastName = "Adams"}
      _people.Add(pers)
      _pets.Add(New Pet With {.Name = "Barley", .Owner = pers})
      _pets.Add(New Pet With {.Name = "Boots", .Owner = pers})
      _pets.Add(New Pet With {.Name = "Blue Moon", .Owner = pers})
    
      pers = New Person With {.FirstName = "Charlotte", .LastName = "Weiss"}
      _people.Add(pers)
      _pets.Add(New Pet With {.Name = "Whiskers", .Owner = pers})
    
      ' Add a person with no pets for the sake of Join examples.
      _people.Add(New Person With {.FirstName = "Arlene", .LastName = "Huff"})
    
      pers = New Person With {.FirstName = "Don", .LastName = "Hall"}
      ' Do not add person to people list for the sake of Join examples.
      _pets.Add(New Pet With {.Name = "Spot", .Owner = pers})
    
      ' Add a pet with no owner for the sake of Join examples.
      _pets.Add(New Pet With {.Name = "Unknown", _
                              .Owner = New Person With {.FirstName = String.Empty, _
                                                        .LastName = String.Empty}})
    End Sub
    
    
    ...
    
    
    Class Person
      Public _firstName As String
      Public _lastName As String
    
      Public Property FirstName() As String
        Get
          Return _firstName
        End Get
        Set(ByVal value As String)
          _firstName = value
        End Set
      End Property
    
      Public Property LastName() As String
        Get
          Return _lastName
        End Get
        Set(ByVal value As String)
          _lastName = value
        End Set
      End Property
    End Class
    
    Class Pet
      Public _name As String
      Public _owner As Person
    
      Public Property Name() As String
        Get
          Return _name
        End Get
        Set(ByVal value As String)
          _name = value
        End Set
      End Property
    
      Public Property Owner() As Person
        Get
          Return _owner
        End Get
        Set(ByVal value As Person)
          _owner = value
        End Set
      End Property
    End Class
    

使用 Join 子句執行內部聯結

INNER JOIN 會將兩個集合中的資料合併。符合指定之索引鍵值的項目都會加入。兩個集合中無法互相符合的項目則會遭排除。

在 Visual Basic 中,LINQ 提供兩個執行 INNER JOIN 的選項,即隱含聯結 (Implicit Join) 和明確聯結 (Explicit Join)。

隱含聯結在 From 子句中指定要聯結 (Join) 的集合,並在 Where 子句中識別符合的索引鍵欄位。Visual Basic 會根據指定的索引鍵欄位,隱含地聯結兩個集合。

當您想要明確指定要在聯結中使用的索引鍵欄位時,可以使用 Join 子句指定明確聯結。在此情況下,仍然可以使用 Where 子句篩選查詢結果。

若要使用 Join 子句執行內部聯結

  • 將下列程式碼加入至您專案中的 Module1 模組,以查看隱含和明確內部聯結 (Inner Join) 的範例。

    Sub InnerJoinExample()
      ' Create two lists.
      Dim people = GetPeople()
      Dim pets = GetPets(people)
    
      ' Implicit Join.
      Dim petOwners = From pers In people, pet In pets _
                      Where pet.Owner Is pers _
                      Select pers.FirstName, PetName = pet.Name
    
        ' Display grouped results.
      Dim output As New System.Text.StringBuilder
      For Each pers In petOwners
        output.AppendFormat( _
          pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
      Next
    
      Console.WriteLine(output)
    
      ' Explicit Join.
      Dim petOwnersJoin = From pers In people _
                          Join pet In pets _
                          On pet.Owner Equals pers _
                          Select pers.FirstName, PetName = pet.Name
    
      ' Display grouped results.
      output = New System.Text.StringBuilder()
      For Each pers In petOwnersJoin
        output.AppendFormat( _
          pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
      Next
    
      Console.WriteLine(output)
    
      ' Both queries produce the following output:
      '
      ' Magnus:    Daisy
      ' Terry:     Barley
      ' Terry:     Boots
      ' Terry:     Blue Moon
      ' Charlotte: Whiskers
    End Sub
    

使用 Group Join 子句執行左外部聯結

LEFT OUTER JOIN 會加入聯結左邊之集合中的所有項目,並且只加入聯結右邊之集合中相符的值。聯結右邊之集合中的項目若在左邊之集合中沒有相符合的項目,就會自查詢結果中排除。

Group Join 子句實際上會執行 LEFT OUTER JOIN。一般所謂的 LEFT OUTER JOIN 跟 Group Join 子句傳回的結果有個不同點,即 Group Join 子句會依照左邊集合中的每個項目,將從聯結右邊集合得到的結果分組。在關聯式資料庫中,LEFT OUTER JOIN 會傳回未分組的查詢結果,結果中的每個項目在聯結兩端的集合中都有相符合的項目。也就是說,每當聯結右邊集合中有相符合的項目時,就會重複列出左邊集合中的項目。當您完成下面的程序後,就會看到大致情形。

您可以擴充查詢,針對每個分組的查詢結果各傳回一個項目,即可以仿造未分組的形式擷取 Group Join 查詢的結果。若要完成這項作業,您必須確定是在已分組集合的 DefaultIfEmpty 方法上執行查詢。這可確保聯結左邊之集合中的項目即使在右邊之集合中沒有相符合的結果,仍然會包含在查詢結果中。您可以將程式碼加入至查詢,以在聯結右邊集合中沒有相符合的值時提供預設結果值。

若要使用 Group Join 子句執行左外部聯結

  • 將下列程式碼加入至您專案中的 Module1 模組,以查看分組之左外部聯結 (Left Outer Join) 和未分組之左外部聯結的範例。

    Sub LeftOuterJoinExample()
      ' Create two lists.
      Dim people = GetPeople()
      Dim pets = GetPets(people)
    
      ' Grouped results.
      Dim petOwnersGrouped = From pers In people _
                             Group Join pet In pets _
                               On pers Equals pet.Owner _
                             Into PetList = Group _
                             Select pers.FirstName, pers.LastName, _
                                    PetList
    
      ' Display grouped results.
      Dim output As New System.Text.StringBuilder
      For Each pers In petOwnersGrouped
        output.AppendFormat(pers.FirstName & ":" & vbCrLf)
        For Each pt In pers.PetList
          output.AppendFormat(vbTab & pt.Name & vbCrLf)
        Next
      Next
    
      Console.WriteLine(output)
    
      ' "Flat" results.
      Dim petOwners = From pers In people _
                      Group Join pet In pets On pers Equals pet.Owner _
                      Into PetList = Group _
                      From pet In PetList.DefaultIfEmpty() _
                      Select pers.FirstName, pers.LastName, _
                             PetName = _
                               If(pet Is Nothing, String.Empty, pet.Name)
      ' This code produces the following output:
      '
      ' Magnus:
      '     Daisy
      ' Terry:
      '     Barley
      '     Boots
      '     Blue Moon
      ' Charlotte:
      '     Whiskers
      ' Arlene:
    
    
      ' Display "flat" results.
      output = New System.Text.StringBuilder()
      For Each pers In petOwners
        output.AppendFormat( _
          pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
      Next
    
      Console.WriteLine(output.ToString())
    End Sub
    
    ' This code produces the following output:
    '
    ' Magnus:       Daisy
    ' Terry:        Barley
    ' Terry:        Boots
    ' Terry:        Blue Moon
    ' Charlotte:    Whiskers
    ' Arlene:     
    

使用複合索引鍵執行聯結

在比對要聯結之集合中的值時,您可以在 Join 或 Group Join 子句中使用 And 關鍵字,識別要使用的多個索引鍵欄位。And 關鍵字會指定所有已指定的索引鍵欄位都必須相符,才能聯結項目。

若要使用複合索引鍵執行聯結

  • 將下列程式碼加入至您專案中的 Module1 模組,以查看使用複合索引鍵之聯結的範例。

    Sub CompositeKeyJoinExample()
      ' Create two lists.
      Dim people = GetPeople()
      Dim pets = GetPets(people)
    
      ' Implicit Join.
      Dim petOwners = From pers In people _
                      Join pet In pets On _
                        pet.Owner.FirstName Equals pers.FirstName _
                        And pet.Owner.LastName Equals pers.LastName _
                      Select pers.FirstName, PetName = pet.Name
    
      ' Display grouped results.
      Dim output As New System.Text.StringBuilder
      For Each pers In petOwners
        output.AppendFormat( _
          pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
      Next
    
      Console.WriteLine(output)
    End Sub
    

執行程式碼

若要加入程式碼以執行範例

  1. 將您專案中 Module1 模組內的 Sub Main 取代為下列程式碼,以執行本主題中的範例。

    Sub Main()
      InnerJoinExample()
      LeftOuterJoinExample()
      CompositeKeyJoinExample()
    
      Console.ReadLine()
    End Sub
    
  2. 按 F5 執行範例。

請參閱

概念

Visual Basic 中的 LINQ 簡介

參考

Join 子句 (Visual Basic)

Group Join 子句 (Visual Basic)

From 子句 (Visual Basic)

Where 子句 (Visual Basic)

其他資源

Visual Basic 中的 LINQ

查詢 (Visual Basic)