Results 1 to 25 of 25

Thread: Join two datatables

  1. #1

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Join two datatables

    Hi everyone, i'm trying to join two datatables, everything i can find online suggests using LINQ, which is fine but i find it's confusing to understand what it is that the examples are actually doing.

    I have one datatable that contains "Inventory" and is named as such, and another datatable that has "CountVarience" named the same as well.

    Both datatables have a column with "product code", i need to add the "product descriptions" column from the "Inventory" table to the "CountVarience" table where the product codes are the same. The end result can be an entirely new datatable that i will then bind to a datagridview.

    I do need to add more columns then just this one, but i figured if i could just get the one working i should be able to repeat it for all the other columns i need to join in the tables.

    Any guidance on how to achieve this correctly would be great

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    Any particular reason that you can just do the join in the database and populate a DataTable with the result? There may well be a reason but I want to check that you have one first. If you don't then you're just making life more complicated for yourself for no reason. That said, a LINQ query would be very similar to a SQL query if you're simply joining two lists, so if you can do one then you should at least be able to make a start on the other.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    Hi Jmcilhinney,

    one set of data comes from a .MDB file and the other set of data is from a .CSV export, so i have moved both sets into separate datatables, and would like to join the two. I don't have a way outside of the application im writing to be able to modify the .csv or the .mdb. if that makes sense. so my application must join them for the user.

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    E.g.
    vb.net Code:
    1. Dim parentTable As New DataTable
    2.  
    3. With parentTable.Columns
    4.     .Add("ParentId", GetType(Integer))
    5.     .Add("ParentName", GetType(String))
    6. End With
    7.  
    8. With parentTable.Rows
    9.     .Add(1, "Parent 1")
    10.     .Add(2, "Parent 2")
    11.     .Add(3, "Parent 3")
    12. End With
    13.  
    14. Dim childTable As New DataTable
    15.  
    16. With childTable.Columns
    17.     .Add("ChildId", GetType(Integer))
    18.     .Add("ChildName", GetType(String))
    19.     .Add("ParentId", GetType(Integer))
    20. End With
    21.  
    22. With childTable.Rows
    23.     .Add(1, "Child 1.1", 1)
    24.     .Add(2, "Child 1.2", 1)
    25.     .Add(3, "Child 1.3", 1)
    26.     .Add(4, "Child 2.1", 2)
    27.     .Add(5, "Child 2.2", 2)
    28.     .Add(6, "Child 2.3", 2)
    29.     .Add(7, "Child 3.1", 3)
    30.     .Add(8, "Child 3.2", 3)
    31.     .Add(9, "Child 3.3", 3)
    32. End With
    33.  
    34. 'Create a deferred query.
    35. Dim query = From parentRow In parentTable.AsEnumerable()
    36.             Join childRow In childTable.AsEnumerable()
    37.             On parentRow.Field(Of Integer)("ParentId") Equals childRow.Field(Of Integer)("ParentId")
    38.             Select New With {.ParentId = parentRow.Field(Of Integer)("ParentId"),
    39.                              .ParentName = parentRow.Field(Of String)("ParentName"),
    40.                              .ChildId = parentRow.Field(Of Integer)("ChildId"),
    41.                              .ChildName = parentRow.Field(Of String)("ChildName")}
    42.  
    43. 'Create a generic List of an anonymous type.
    44. Dim list = query.ToList()
    The demonstrates a basic join and shows how it's very similar to a SQL join. This example creates a List(Of T) where T is an anonymous type. You can bind that list directly to a grid or whatever you like. You could also define your own type if you need to be able to access its members outside the code that creates the instances, which you can't really do with an anonymous type. If you want a DataTable then you'll have to create one yourself. There is a CopyToDataTable method that is part of LINQ to DataSet but you need DataRows to begin with in order to call that, and you can't have DataRows without a DataTable.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    so i have just tired to implement this for my case,

    but i'm unclear on how i bind this to my datagridview correctly. I can use, DGV.Datasource = list

    but then the datagridview does not let me sort any of the columns as i would normally be able to with data from my datatables.

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    A List(Of T) has a Sort method. If you want to sort the grid with a bound List(Of T) then you need to do the sorting programmatically and call that method appropriately. If you want the automatic sorting built into the DataView class then you'll need to populate a DataTable instead of creating a List(Of T). I'm not going to go into details of programmatic sorting here because this thread is about joining DataTables, which is a completely separate topic.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    So you answer sort of works for me, this is the code i have created:

    Code:
     Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
                            Join InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
                On CountedRow.Field(Of String)("Product Code") Equals InventoryRow.Field(Of String)("Product Code")
                            Select New With {.ProductCode = CountedRow.Field(Of String)("Product Code"),
                                            .Model = InventoryRow.Field(Of String)("Model"),
                                            .FullDescription = InventoryRow.Field(Of String)("Description"),
                                            .Class = CountedRow.Field(Of String)("CLASS"),
                                            .BatchNumber = CountedRow.Field(Of String)("Batch Number"),
                                            .OriginalCost = CountedRow.Field(Of String)("Original Cost"),
                                            .CountedCost = CountedRow.Field(Of String)("Counted Cost"),
                                            .CostVarience = CountedRow.Field(Of String)("Cost Variance"),
                                            .OriginalSOH = CountedRow.Field(Of String)("Original SOH"),
                                            .Counted = CountedRow.Field(Of String)("Counted"),
                                            .Variance = CountedRow.Field(Of String)("Variance")}
    This will populate the list, and it will pull in the Model, and Inventory Names from the , where the product codes match.

    the only problem i have, is that if on my STOCK datatable a product code appeared 7 times, because that product has 7 different "batches"
    the output list is also gives me each single batch, seven times over. so i end up with 7 x 7 for my output list.
    v
    is it the type of JOIN in using or something in the query itself that is causing that? From my understanding in SQL terms its a LEFT JOIN i want to perform, where i get all the results from STOCK datatable and matching records from INVENTORY.

    i appreciate your help

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    This code is performing an inner join. The point of an inner join is to provide one record in the output for every pair of records in the two inputs that match on the criteria you specify. Doing an outer join instead is not going to help you because outer joins generate at least as many records in the output as inner joins and possibly more. Your problem is that you're not defining a parent/child relationship between the two inputs. What exactly do you expect the output to look like? If each of the 7 records in one input is only supposed to match 1 record in the other output rather than all 7 with the same Product Code then obviously you haven't specified sufficient criteria in your On clause. If you expect the data to be matched by more than just the Product Code then you have to specify that in your query, because it won't happen due to wishful thinking. What criteria do you actually want to match the data on?
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    BTW, I know I said I wouldn't but here's an example of programmatic sorting:
    vb.net Code:
    1. Private items As New List(Of Tuple(Of String, Integer))
    2. Private ReadOnly sortOrderByColumnIndex As New Dictionary(Of Integer, SortOrder)
    3.  
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5.     items.AddRange({Tuple.Create("A", 2),
    6.                     Tuple.Create("B", 4),
    7.                     Tuple.Create("C", 1),
    8.                     Tuple.Create("D", 3)})
    9.  
    10.     BindingSource1.DataSource = items
    11.     DataGridView1.DataSource = BindingSource1
    12.  
    13.     For Each column As DataGridViewColumn In DataGridView1.Columns
    14.         column.SortMode = DataGridViewColumnSortMode.Programmatic
    15.         sortOrderByColumnIndex.Add(column.Index, SortOrder.None)
    16.     Next
    17. End Sub
    18.  
    19. Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
    20.     Dim columnIndex = e.ColumnIndex
    21.     Dim sortOrder = sortOrderByColumnIndex(columnIndex)
    22.  
    23.     Select Case columnIndex
    24.         Case 0
    25.             If sortOrder = SortOrder.Ascending Then
    26.                 items.Sort(Function(x, y) y.Item1.CompareTo(x.Item1))
    27.                 sortOrderByColumnIndex(columnIndex) = SortOrder.Descending
    28.             Else
    29.                 items.Sort(Function(x, y) x.Item1.CompareTo(y.Item1))
    30.                 sortOrderByColumnIndex(columnIndex) = SortOrder.Ascending
    31.             End If
    32.         Case 1
    33.             If sortOrder = SortOrder.Ascending Then
    34.                 items.Sort(Function(x, y) y.Item2.CompareTo(x.Item2))
    35.                 sortOrderByColumnIndex(columnIndex) = SortOrder.Descending
    36.             Else
    37.                 items.Sort(Function(x, y) x.Item2.CompareTo(y.Item2))
    38.                 sortOrderByColumnIndex(columnIndex) = SortOrder.Ascending
    39.             End If
    40.     End Select
    41.  
    42.     BindingSource1.ResetBindings(False)
    43. End Sub
    Note that you can't use an anonymous type unless you want to use Reflection in the comparisons. You also need to bind via a BindingSource, because the change in the underlying List won't be reflected in the grid automatically. Finally, this code does not display the sorting glyphs on the column headers. I'll leave that to you.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  10. #10

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    hi jmcilhinney

    i would only be able to use the product code as the thing to match the two, as its the only field the is the same between them.

    but if the STOCK.csv file has list of product codes, and those product codes appear more then once due to their batches

    for example

    Code:
    +---------------+-------+---------+--------------+
    | Product Code  | Batch | Counted | Original SOH |
    +---------------+-------+---------+--------------+
    | Apples        |  2252 |      10 |           10 |
    | Apples        |  2253 |       4 |            4 |
    | Apples        |  2265 |       0 |            2 |
    +---------------+-------+---------+--------------+
    So in the CSV file the row for apples appears 3 times.

    i want the out out to pull the model name and description from the inventory file.

    Code:
    +--------------+-------------+---------------------+-------+---------+--------------+
    | Product Code |    Model    |    Description      | Batch | Counted | Original SOH |
    +--------------+-------------+---------------------+-------+---------+--------------+
    | Apples       | Red Apples  | Grown In Australia  |  2252 |      10 |           10 |
    | Apples       | Red Apples  | Grown In Australia  |  2253 |       4 |            4 |
    | Apples       | Red Apples  | Grown In Australia  |  2265 |       0 |            2 |
    +--------------+-------------+---------------------+-------+---------+--------------+
    there would still only be the 3 rows, but model and description would now be added.

    Is it possible to do a "SELECT TOP" like in SQL? and just pull the TOP model and description and match that to my rows in the STOCK datatable?
    Last edited by AndyAndromeda; Mar 25th, 2021 at 09:00 PM.

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    In that case, it's not the inventory table you want to join with at all. What you want is to create a new list/table that contains distinct Product Code/Model/Description combinations first, then join that with the stock table. Without having tested, I believe that you should be able to change this:
    vb.net Code:
    1. Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
    2.             Join InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
    3.             On CountedRow.Field(Of String)("Product Code") Equals InventoryRow.Field(Of String)("Product Code")
    4.             Select New With {.ProductCode = CountedRow.Field(Of String)("Product Code"),
    5.                              .Model = InventoryRow.Field(Of String)("Model"),
    6.                              .FullDescription = InventoryRow.Field(Of String)("Description"),
    7.                              .Class = CountedRow.Field(Of String)("CLASS"),
    8.                              .BatchNumber = CountedRow.Field(Of String)("Batch Number"),
    9.                              .OriginalCost = CountedRow.Field(Of String)("Original Cost"),
    10.                              .CountedCost = CountedRow.Field(Of String)("Counted Cost"),
    11.                              .CostVarience = CountedRow.Field(Of String)("Cost Variance"),
    12.                              .OriginalSOH = CountedRow.Field(Of String)("Original SOH"),
    13.                              .Counted = CountedRow.Field(Of String)("Counted"),
    14.                              .Variance = CountedRow.Field(Of String)("Variance")}
    to this:
    vb.net Code:
    1. Dim distinctInventory = From InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
    2.                         Select New With {.ProductCode = InventoryRow.Field(Of String)("Product Code"),
    3.                                          .Model = InventoryRow.Field(Of String)("Model"),
    4.                                          .FullDescription = InventoryRow.Field(Of String)("Description")}
    5.                         Distinct
    6. Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
    7.             Join Inventory In distinctInventory
    8.             On CountedRow.Field(Of String)("Product Code") Equals Inventory.ProductCode
    9.             Select New With {.ProductCode = CountedRow.Field(Of String)("Product Code"),
    10.                              .Model = Inventory.Model,
    11.                              .FullDescription = Inventory.FullDescription,
    12.                              .Class = CountedRow.Field(Of String)("CLASS"),
    13.                              .BatchNumber = CountedRow.Field(Of String)("Batch Number"),
    14.                              .OriginalCost = CountedRow.Field(Of String)("Original Cost"),
    15.                              .CountedCost = CountedRow.Field(Of String)("Counted Cost"),
    16.                              .CostVarience = CountedRow.Field(Of String)("Cost Variance"),
    17.                              .OriginalSOH = CountedRow.Field(Of String)("Original SOH"),
    18.                              .Counted = CountedRow.Field(Of String)("Counted"),
    19.                              .Variance = CountedRow.Field(Of String)("Variance")}
    Last edited by jmcilhinney; Mar 25th, 2021 at 10:18 PM.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  12. #12

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    I gave this a test. but this still gives me the duplicates.

  13. #13
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    I wasn't previously aware of this difference (or hadn't considered it sufficiently, at least) but, while C# will compare each property of an anonymous type to determine uniqueness, VB will only compare those properties declared as key properties. That means that you need to declare each property as key in the first query:
    vb.net Code:
    1. Dim distinctInventory = From InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
    2.                         Select New With {Key .ProductCode = InventoryRow.Field(Of String)("Product Code"),
    3.                                          Key .Model = InventoryRow.Field(Of String)("Model"),
    4.                                          Key .FullDescription = InventoryRow.Field(Of String)("Description")}
    5.                         Distinct
    Last edited by jmcilhinney; Mar 25th, 2021 at 10:18 PM.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  14. #14

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    BY GEORGE jmcilhinney you have done it!!!

    your a genius, its working now

    thank you for all your help today!

  15. #15
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    Quote Originally Posted by jmcilhinney View Post
    Note that you can't use an anonymous type unless you want to use Reflection in the comparisons.
    Another option would be to use late binding. This is one of the few situations in which I'd somewhat approve of that. You should still have Option Strict On at the project level and then you would create a partial class in a file with Option Strict Off. For example, you could do this:
    vb.net Code:
    1. Private items As New List(Of Object)
    2. Private ReadOnly sortOrderByColumnIndex As New Dictionary(Of Integer, SortOrder)
    3.  
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5.     items.AddRange({New With {.Letter = "A", .Number = 2},
    6.                     New With {.Letter = "B", .Number = 4},
    7.                     New With {.Letter = "C", .Number = 1},
    8.                     New With {.Letter = "D", .Number = 3}})
    9.  
    10.     BindingSource1.DataSource = items
    11.     DataGridView1.DataSource = BindingSource1
    12.  
    13.     For Each column As DataGridViewColumn In DataGridView1.Columns
    14.         column.SortMode = DataGridViewColumnSortMode.Programmatic
    15.         sortOrderByColumnIndex.Add(column.Index, SortOrder.None)
    16.     Next
    17. End Sub
    and create, for example, Form1.StrictOff.vb containing this code:
    vb.net Code:
    1. Option Strict Off
    2.  
    3. Partial Public Class Form1
    4.  
    5.     Private Sub DataGridView1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
    6.         Dim columnIndex = e.ColumnIndex
    7.         Dim sortOrder = sortOrderByColumnIndex(columnIndex)
    8.  
    9.         Select Case columnIndex
    10.             Case 0
    11.                 If sortOrder = SortOrder.Ascending Then
    12.                     items.Sort(Function(x, y) y.Letter.CompareTo(x.Letter))
    13.                     sortOrderByColumnIndex(columnIndex) = SortOrder.Descending
    14.                 Else
    15.                     items.Sort(Function(x, y) x.Letter.CompareTo(y.Letter))
    16.                     sortOrderByColumnIndex(columnIndex) = SortOrder.Ascending
    17.                 End If
    18.             Case 1
    19.                 If sortOrder = SortOrder.Ascending Then
    20.                     items.Sort(Function(x, y) y.Number.CompareTo(x.Number))
    21.                     sortOrderByColumnIndex(columnIndex) = SortOrder.Descending
    22.                 Else
    23.                     items.Sort(Function(x, y) x.Number.CompareTo(y.Number))
    24.                     sortOrderByColumnIndex(columnIndex) = SortOrder.Ascending
    25.                 End If
    26.         End Select
    27.  
    28.         BindingSource1.ResetBindings(False)
    29.     End Sub
    30.  
    31. End Class
    It's still part of the same class so the code still has access to the same members of that class, but late binding is allowed so those Letter and Number properties will not be rejected by the compiler.

    That said, if you're going to do this anyway, I'd be tempted to just declare a dedicated class and not use an anonymous type in the first place.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  16. #16

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    if i needed to take the query a step further and match two columns: i currently have:

    Code:
     Dim distinctInventory = From InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
                                        Select New With {Key .ProductCode = InventoryRow.Field(Of String)("Product Code"),
                                             Key .Model = InventoryRow.Field(Of String)("Model"),
                                             Key .FullDescription = InventoryRow.Field(Of String)("Description"),
                                             Key .ON_INVOICE = InventoryRow.Field(Of Integer?)("ON INVOICE"),
                                             Key .BatchNumber = InventoryRow.Field(Of String)("Batch_Number")}
                                        Distinct
    
                Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
                            Join Inventory In distinctInventory
                On CountedRow.Field(Of String)("Product Code") Equals Inventory.ProductCode
                            Order By CountedRow.Field(Of String)("Class")
                            Select New With {.Class = CountedRow.Field(Of String)("Class"),
                                 .ProductCode = CountedRow.Field(Of String)("Product Code"),
                                 .Model = Inventory.Model,
                                 .Description = Inventory.FullDescription,
                                 .Batch_Number = CountedRow.Field(Of String)("Batch Number"),
                                 .Original_Cost = CountedRow.Field(Of String)("Original Cost"),
                                 .Counted_Cost = CountedRow.Field(Of String)("Counted Cost"),
                                 .Cost_Varience = CountedRow.Field(Of String)("Cost Variance"),
                                 .Original_SOH = CountedRow.Field(Of String)("Original SOH"),
                                 .Counted = CountedRow.Field(Of String)("Counted"),
                                 .Variance = CountedRow.Field(Of String)("Variance"),
                                 .On_Invoice = Inventory.ON_INVOICE,
                                 .INV_Batch_Number = Inventory.BatchNumber}
    But my STOCK datatable has a column "Batch Number" where some batch numbers start with "0000" and as such they have been dropped of in the export of the csv.
    On the up side the Inventory datatable contains the full batch number,

    is there a way to take the batch number column and say where is ends LIKE the one in the inventory file then add that batch number to a new column in the query?

    for the sake of checking that the output is correct for now i'd like to keep the existing batch number column and add a new column called "FULL BATCH NUMBER" with the matched up batch number. much the same way the model and description columns were added in.

  17. #17
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    You can't have different numbers of columns in each row, but you can decide what goes into each column for a row so it could be NULL or it could be a value. As for a Where clause, its a Where clause. You shouldn't need me to explain how to write a simple Where clause. Not before at least trying for yourself, anyway.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  18. #18

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    hey mate, i think maybe i havnt explained my self very well.

    I did try to add a where, but im not sure if im adding this to the top half of the statment with the DISTINCT or the lower half.

    I am also not sure if i should be preforming the LINQ statement you helped with first, and then preform another one that just solves the "0000" number problem with the batch column .

    for better understanding here is two tables of what i would like to acheive.

    CURRENT TABLE
    Code:
    +---------------+-------+---------+--------------+
    | Product Code  | Batch | Counted | Original SOH |
    +---------------+-------+---------+--------------+
    | Apples        |  2252 |      10 |           10 |
    | Apples        |  2253 |       4 |            4 |
    | Apples        |  2265 |       0 |            2 |
    +---------------+-------+---------+--------------+
    FINAL OUTPUT TABLE
    Code:
    +---------------+-------+---------+--------------+------------+
    | Product Code  | Batch | Counted | Original SOH | Full Batch |
    +---------------+-------+---------+--------------+------------+
    | Apples        |  2252 |      10 |           10 | 00002252   |
    | Apples        |  2253 |       4 |            4 | 00002253   |
    | Apples        |  2265 |       0 |            2 | 00002265   |
    +---------------+-------+---------+--------------+------------+
    the column FULL BATCH is from the "Inventory" table, and WHERE its LIKE the BATCH in the table "stock", it gets added to the FULL BATCH coluumn.

    im very much self taught when it comes to SQL, and while the LINQ is very similar the differences are a little confusing, especially with more complex things like the DISTINCT statement.

  19. #19
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    Quote Originally Posted by AndyAndromeda View Post
    I did try to add a where, but im not sure if im adding this to the top half of the statment with the DISTINCT or the lower half.
    ALWAYS show us what you tried. We only know what you tell us so, if you don't tell us you've done something, you've done nothing as far as we're concerned. ALWAYS provide a FULL and CLEAR explanation of the problem: what you're trying to do, how you're trying to do it and what happened when you tried.

    As for where to put it, as always, think about the logic first and then write the code to implement the logic. The first query gives you a list of distinct inventory records to join to the stock records. Do you want to filter that inventory list? If so then you can put the filter on the first query. If not then you can't. I say that "can" and "can't" because you can filter the inventory in either query - both queries involve inventory - but you can only filter the stock in the second.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  20. #20

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    I appreciate your help, it was late last night when i posted and i was a bit fried from trying to get other various things working when i decided to come back to this.

    I did manage last night to add in the Full Batch Coloumn, but it didnt always allign to the same batch that was in that particular row. So i know i need to add the LIKE operator in. and have them match up like that.

    I will give it anothr go once i get home from work today

  21. #21
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    I've done very few joins in LINQ myself but, without having tested, I think that the Join clause only supports the Equals operator. If you want to use other operators then I think you'd have to use the Where clause. The Where clause accepts any Boolean expression though, so you can use anything that you could use in an If statement, e.g.
    vb.net Code:
    1. Where item1.TextProperty.TrimStart("0"c) = item2.TextProperty
    That will include joined items with a similar value in TextProperty, even if item1 has some leading zeroes. That seems to be the sort of thing you're talking about.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  22. #22
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    It occurred to me after writing that that it does test for equality so you may be able to include it in the Join clause after all.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  23. #23
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,129

    Re: Join two datatables

    Quote Originally Posted by AndyAndromeda View Post
    So you answer sort of works for me, this is the code i have created:

    Code:
     Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
                            Join InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
                On CountedRow.Field(Of String)("Product Code") Equals InventoryRow.Field(Of String)("Product Code")
                            Select New With {.ProductCode = CountedRow.Field(Of String)("Product Code"),
                                            .Model = InventoryRow.Field(Of String)("Model"),
                                            .FullDescription = InventoryRow.Field(Of String)("Description"),
                                            .Class = CountedRow.Field(Of String)("CLASS"),
                                            .BatchNumber = CountedRow.Field(Of String)("Batch Number"),
                                            .OriginalCost = CountedRow.Field(Of String)("Original Cost"),
                                            .CountedCost = CountedRow.Field(Of String)("Counted Cost"),
                                            .CostVarience = CountedRow.Field(Of String)("Cost Variance"),
                                            .OriginalSOH = CountedRow.Field(Of String)("Original SOH"),
                                            .Counted = CountedRow.Field(Of String)("Counted"),
                                            .Variance = CountedRow.Field(Of String)("Variance")}
    This will populate the list, and it will pull in the Model, and Inventory Names from the , where the product codes match.

    the only problem i have, is that if on my STOCK datatable a product code appeared 7 times, because that product has 7 different "batches"
    the output list is also gives me each single batch, seven times over. so i end up with 7 x 7 for my output list.
    v
    is it the type of JOIN in using or something in the query itself that is causing that? From my understanding in SQL terms its a LEFT JOIN i want to perform, where i get all the results from STOCK datatable and matching records from INVENTORY.

    i appreciate your help
    I think you have to add Group Join

    Code:
    Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
                         Group Join InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
    '...more code
    something like
    Code:
      Dim Query = From t1 In datatable1.AsEnumerable() 
          Group Join t2 In datatable2.AsEnumerable()
    '...more code
    I personally would add the CSV to the .mdb and perform the SQL there
    Last edited by ChrisE; Mar 28th, 2021 at 01:52 AM.
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  24. #24

    Thread Starter
    Member
    Join Date
    Nov 2019
    Posts
    55

    Re: Join two datatables

    Code:
    Dim distinctInventory = From InventoryRow In acc.GetDataTable("INVXLS").AsEnumerable()
                                        Select New With {Key .ProductCode = InventoryRow.Field(Of String)("Product Code"),
                                             Key .Model = InventoryRow.Field(Of String)("Model"),
                                             Key .FullDescription = InventoryRow.Field(Of String)("Description"),
                                             Key .ON_INVOICE = InventoryRow.Field(Of Integer?)("ON INVOICE"),
                                             Key .BatchNumber = InventoryRow.Field(Of String)("Batch_Number")} 'this batch number just adds the rows in. 
                                        Distinct
    
                Dim query = From CountedRow In acc.GetDataTable("STOCK").AsEnumerable()
                            Join Inventory In distinctInventory
                            On CountedRow.Field(Of String)("Product Code") Equals Inventory.ProductCode
                            Where Inventory.BatchNumber.TrimStart("0"c) = CountedRow.Field(Of String)("Batch Number")
                            Order By CountedRow.Field(Of String)("Class")
                            Select New With {.Class = CountedRow.Field(Of String)("Class"),
                                 .ProductCode = CountedRow.Field(Of String)("Product Code"),
                                 .Model = Inventory.Model,
                                 .Description = Inventory.FullDescription,
                                 .Batch_Number = CountedRow.Field(Of String)("Batch Number"),
                                 .Original_Cost = CountedRow.Field(Of String)("Original Cost"),
                                 .Counted_Cost = CountedRow.Field(Of String)("Counted Cost"),
                                 .Cost_Varience = CountedRow.Field(Of String)("Cost Varience"),
                                 .Original_SOH = CountedRow.Field(Of String)("Original SOH"),
                                 .Counted = CountedRow.Field(Of String)("Counted"),
                                 .Varience = CountedRow.Field(Of String)("Varience"),
                                 .On_Invoice = Inventory.ON_INVOICE,
                                 .INV_Batch_Number = Inventory.BatchNumber}
    i have tried the above and moved the where statement to other places in the LINQ query but i can't get it to work, also i feel the WHERE statement needs something more added to it, in my mind i'm just saying where two things match, i'm not currently saying then add this column in. but i'm not sure how that syntax would look.

  25. #25
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Join two datatables

    Quote Originally Posted by AndyAndromeda View Post
    i feel the WHERE statement needs something more added to it, in my mind i'm just saying where two things match, i'm not currently saying then add this column in. but i'm not sure how that syntax would look.
    No, that's nothing to do with the Where clause. As I already told you, you can't have different columns in different records in the output. If any record needs a column then every record has to have that column. It's when you set the value of that column, which is actually a property in this case, that you decide what that value should be, e.g.
    vb.net Code:
    1. .SomeProperty = If(row.Field(Of String)("SomeColumn") = someValue, row.Field(Of String)("SomeOtherColumn"), (string)null)
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width