таблицы данных — добавление / объединение значений одной таблицы в другую

#asp.net #vb.net #datatable

#asp.net #vb.net #datatable

Вопрос:

Для нового проекта требуется, чтобы у нас было два сервера, настроенных для приема запросов. Изначально у нас была система отчетов, которая запрашивала базу данных и возвращала пользователю различные детали. Теперь нам, очевидно, нужно запросить две базы данных на отдельных серверах и объединить эту информацию для предоставления отчетов в режиме реального времени.

Мой план состоит в том, чтобы запросить обе базы данных отдельно и записать эти значения в таблицы данных (которые всегда будут иметь одинаковые столбцы, поскольку две базы данных спроектированы одинаково), а затем попытаться объединить эти две таблицы данных, а затем привязать их к таблице. у меня это работает до определенного момента, но я не знаю, что делать дальше … все запросы работают нормально, и я могу перенести оба набора sql-запросов в отдельный datatable, чего я не знаю, как сделать, так это объединить их, чтобы любые данные (например, с той же датой) добавлялись, чтобы получить общее количество с двух серверов, и если дата существует в одной базе данных, но не в другой, это все равно должно отображаться … я надеюсь, это достаточно ясно.

Когда я использую это:

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

        GridViewBreakDown.DataSource = tblBreakdownA
        GridViewBreakDown.DataBind()
  

Две таблицы данных действительно сливаются, однако вторая просто сливается ниже первой, поэтому в итоге некоторые даты повторяются, но содержат разные значения, т. е

База данных 1
01 января — 10 просмотров
, 03 января — 15 просмотров
, 04 января — 5 просмотров

DB 2
02 января — 5 обращений
03 января — 10 обращений
05 января — 5 обращений

То, что я вижу на выходе, выглядит примерно так:
01 января — 10 просмотров
, 03 января — 15 просмотров
, 04 января — 5 просмотров
, 02 января — 5 просмотров
, 03 января — 10 просмотров
, 05 января — 5 просмотров

И то, что я ищу, должно быть примерно таким
01 января — 10 просмотров
, 02 января — 5 просмотров
, 03 января — 25 просмотров
, 04 января — 5 просмотров
, 05 января — 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()
  

Ответ №1:

Я думаю, что то, что вы ищете, — это группировка. Вы могли бы сделать это с помощью Linq или T-SQL, но по сути вы хотите сгруппировать записи по дате и отобразить сумму совпадений внутри этой группы.

Примеры группировки:

Linq to SQL Group By

T-SQL Группирует по

Редактировать:

Я надеюсь, @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  
  

Комментарии:

1. Привет, в инструкциях SQL используется GROUP BY для получения данных в нужном мне формате, но можете ли вы использовать GROUP BY для объединения двух таблиц данных (или даже для группировки двух отдельных инструкций sql, которые используют разные строки подключения?)

2. @allanmayberry88 Я отредактировал свой пост, чтобы объединить тестовый пример @Rene147 с Linq, необходимым для выполнения того, что вы просили. Вероятно, это можно было бы сделать проще, но я разбил это на маленькие шаги, что сделало инструкцию намного длиннее, чем я ожидал =/ извините. Надеюсь, это все же поможет!

3. @Smudge202 — Спасибо, что перезвонили мне, я рассмотрю ваше предложение и посмотрю, работает ли оно — Я добавил больше кода к своему вопросу, который, возможно, немного прояснит то, чего я пытаюсь достичь. Спасибо!

4. Теперь я понимаю. Опубликованный мной код все еще применяется. Я не силен во внешних компонентах, но переменная results, которую я объявил в своем коде, представляет собой коллекцию анонимного типа, которая имеет свойства для Date и Hits. Вы должны иметь возможность заменить мое объявление результатов на «GridViewBreakDown.DataSource = <инструкция linq>» (или просто GridViewBreakDown.DataSource = результаты)

5. Очень признателен! Я вернусь к вам после тестирования! Спасибо!

Ответ №2:

Это сделает то, о чем вы просили, но на 100% согласен с Smudge, было бы намного лучше сделать GroupBy в SQL statment

 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
  

Комментарии:

1. Потому что я люблю . Выражение ForEach() lamda для запутывания коллег, следующая строка выполняет то же самое, что и ваш цикл, но, конечно, круче =D dt1.DefaultView. Итоговый (True, «Дата»). В количестве. ToList. ForEach(Sub(n) строка. Формат («Дата — {0} имела {1} совпадений», n.Item(0), (HitsOnGivenDate(CDate(n.Item(0)), dt1) HitsOnGivenDate(CDate(n.Item(0)), dt2)). toString))