#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, но по сути вы хотите сгруппировать записи по дате и отобразить сумму совпадений внутри этой группы.
Примеры группировки:
Редактировать:
Я надеюсь, @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))