【问题标题】:datatables - adding/merging the values of one table to another数据表 - 将一个表的值添加/合并到另一个表
【发布时间】:2011-05-06 11:14:54
【问题描述】:

一个新项目需要我们设置两台服务器来接受请求。最初,我们有一个报告系统,它查询数据库并将各种详细信息返回给用户。我们现在显然需要查询不同服务器上的两个数据库并合并这些信息以提供实时报告。

我的计划是分别查询两个数据库并将这些值写入数据表(这将始终具有相同的列,因为两个数据库的设计相同)然后尝试合并这两个数据表,然后将其数据绑定到网格视图。我让它工作到一定程度,但不知道下一步该做什么......查询一切正常,我能够将两组 sql 查询拉到单独的数据表中,我不知道该怎么做是合并这些以便添加任何数据(例如同一日期)以提供两台服务器的总数,并且如果一个数据库上存在日期但另一个数据库上不存在日期,则仍应显示...我希望这很清楚够了。

当我使用这个时:

tblBreakdownA.Merge(tblBreakdownB, False, MissingSchemaAction.Add)

        GridViewBreakDown.DataSource = tblBreakdownA
        GridViewBreakDown.DataBind()

这两个数据表确实合并了,但是第二个数据表只是简单地合并到第一个数据表之下,所以我最终得到了一些重复但持有不同值的日期,即

数据库 1
1 月 1 日 - 10 次点击
1 月 3 日 - 15 次点击
1 月 4 日 - 5 次点击

数据库 2
1 月 2 日 - 5 次点击
1 月 3 日 - 10 次点击
1 月 5 日 - 5 次点击

我看到的输出是这样的:
1 月 1 日 - 10 次点击
1 月 3 日 - 15 次点击
1 月 4 日 - 5 次点击
1 月 2 日 - 5 次点击
1 月 3 日 - 10 次点击
1 月 5 日 - 5 次点击

而我正在寻找的应该是这样的
1 月 1 日 - 10 次点击
1 月 2 日 - 5 次点击
1 月 3 日 - 25 次点击
1 月 4 日 - 5 次点击
1 月 5 日 - 5 次点击

一如既往,非常感谢任何帮助!

编辑 - 添加源代码

下面是更多代码,可以更好地解释我想要实现的目标。

'*******POPULATE GRIDVIEW-BREAKDOWN CONTROL**************
    Dim tblBreakdownA As DataTable 'holds results from Database A
    Dim tblBreakdownB As DataTable 'holds results from Database B

    GridViewBreakDown.Visible = True
    lblBreakdown.Visible = True

    'Connection to Database A
    Using myConnection As New SqlConnection
        myConnection.ConnectionString = CONNECTION STRING
        Dim mySelect As New SqlCommand
        mySelect.Connection = myConnection
        mySelect.CommandText = "SELECT STATEMENT"
        myConnection.Open()
        Dim myReader As SqlDataReader = mySelect.ExecuteReader()

        tblBreakdownA = New DataTable("Breakdown")
        tblBreakdownA.Load(myReader)

        myReader.Close()
        myConnection.Close()
    End Using

    'Connection to Database B
    Using myConnection As New SqlConnection
        myConnection.ConnectionString =CONNECTION STRING
        Dim mySelect As New SqlCommand
        mySelect.Connection = myConnection
        mySelect.CommandText = "SELECT STATEMENT"
        myConnection.Open()
        Dim myReader As SqlDataReader = mySelect.ExecuteReader()

        tblBreakdownB = New DataTable("Breakdown")
        tblBreakdownB.Load(myReader)

        myReader.Close()
        myConnection.Close()
    End Using

    tblBreakdownA.Merge(tblBreakdownB, False, MissingSchemaAction.Add)

    GridViewBreakDown.DataSource = tblBreakdownA
    GridViewBreakDown.DataBind()

【问题讨论】:

    标签: asp.net vb.net datatable


    【解决方案1】:

    我认为您正在寻找的是分组。您可以使用 Linq 或 T-SQL 执行此操作,但本质上您希望按日期对记录进行分组,并显示该组内的命中总和。

    分组示例:

    Linq to SQL Group By

    T-SQL Group By

    编辑:

    我希望 @Rene147 不介意我修改他发布的代码来演示您需要的 Linq 语法(它有点冗长而且一团糟,但它可以工作并演示了 Linqs 的一些简洁功能......) :

    Public Sub StackTest()
        Dim dt1 As New DataTable
        Dim dt2 As New DataTable
    
        '   Create some test data
        dt1.Columns.Add("Date", GetType(Date))
        dt1.Columns.Add("Hits", GetType(Integer))
    
        dt2.Columns.Add("Date", GetType(Date))
        dt2.Columns.Add("Hits", GetType(Integer))
    
    
        dt1.Rows.Add(#1/1/2011#, 10)
        dt1.Rows.Add(#3/1/2011#, 15)
        dt1.Rows.Add(#4/1/2011#, 5)
    
        dt2.Rows.Add(#2/1/2011#, 5)
        dt2.Rows.Add(#3/1/2011#, 10)
        dt2.Rows.Add(#5/1/2011#, 5)
    
        '   Merge the two results
        dt1.Merge(dt2)
    
        dt1.DefaultView.Sort = "Date"
    
        Dim results = (From anomList In
                       (From mergedTables In dt1.DefaultView.ToTable(True, "Date", "Hits").AsEnumerable
                        Select [Date] = mergedTables.Item(0), Hits = mergedTables.Item(1))
                    Group anomList By anomList.Date Into g = Group
                    Select New With {.[Date] = [Date], .Hits = g.Sum(Function(n) CInt(n.Hits))}).OrderBy(Function(n) n.Date)
    End Sub  
    

    【讨论】:

    • 您好,在 SQL 语句中使用了 GROUP BY 来获取我需要的格式的数据,但是您可以使用 GROUP BY 来组合两个数据表(甚至可以将两个单独的使用不同连接字符串的sql语句?)
    • @allanmayberry88 我已经编辑了我的帖子,将@Rene147 的测试用例与执行您所要求的Linq 相结合。它可能比这更容易完成,但我把它分解成一些小步骤,这使得声明比我预期的要长得多 =/对不起。希望它有所帮助!
    • @Smudge202 - 感谢您回复我,我会看看您的建议,看看它是否有效 - 我在我的问题中添加了更多代码,这可能使它更清晰一点我想要达到的目标。谢谢!
    • 我现在明白了。我发布的代码仍然适用。我在前端组件方面并不出色,但我在代码中声明的结果变量是一个匿名类型的集合,它具有 Date 和 Hits 的属性。您应该能够将我的结果声明切换为“GridViewBreakDown.DataSource = ”(或简单地说 GridViewBreakDown.DataSource = results)
    • 非常感谢!测试后我会回来找你的!谢谢!
    【解决方案2】:

    这将满足您的要求,但 100% 同意 Smudge 在 SQL 语句中执行 GroupBy 会好得多

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim dt1 As New DataTable
        Dim dt2 As New DataTable
    
        '   Create some test data
        dt1.Columns.Add("Date", GetType(Date))
        dt1.Columns.Add("Hits", GetType(Integer))
    
        dt2.Columns.Add("Date", GetType(Date))
        dt2.Columns.Add("Hits", GetType(Integer))
    
    
        dt1.Rows.Add(CDate("01/01/2011"), 10)
        dt1.Rows.Add(CDate("03/01/2011"), 15)
        dt1.Rows.Add(CDate("04/01/2011"), 5)
    
        dt2.Rows.Add(CDate("02/01/2011"), 5)
        dt2.Rows.Add(CDate("03/01/2011"), 10)
        dt2.Rows.Add(CDate("05/01/2011"), 5)
    
        '   Merge the two results
        dt1.Merge(dt2)
    
        dt1.DefaultView.Sort = "Date"
    
        '    Select all of the distinct dates 
        For Each row As DataRow In dt1.DefaultView.ToTable(True, "Date").Rows
    
            Dim TotalForDay As Integer = 0
    
            TotalForDay = HitsOnGivenDate(row.Item(0), dt1)
            TotalForDay += HitsOnGivenDate(row.Item(0), dt2)
    
            Debug.WriteLine(String.Format("Date - {0} had {1} hits", row.Item(0), TotalForDay))
        Next
    
    End Sub
    
    Private Function HitsOnGivenDate(ByVal SearchDate As Date, ByVal SearchTable As DataTable) As Integer
    
        Dim HitsOnDay As Integer = 0
    
        Dim SearchString As String = String.Format("Date = '{0}'", SearchDate)
    
        '   Selete all the rows for this given date
        For Each Row As DataRow In SearchTable.Select(SearchString)
            HitsOnDay += Row.Item(1)
        Next
    
        Return HitsOnDay
    End Function
    

    【讨论】:

    • 因为我喜欢 .ForEach() lamda 表达式来混淆同事,所以以下行与您的循环相同 - 但当然更酷 =D dt1.DefaultView.ToTable(True, "Date") .AsEnumerable.ToList.ForEach(Sub(n) String.Format("Date - {0} 有 {1} 次点击", n.Item(0), (HitsOnGivenDate(CDate(n.Item(0)), dt1) + HitsOnGivenDate(CDate(n.Item(0)), dt2)).ToString))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多