I'm not a regular user of LINQ so this question might be as dumb as possible for an expert :)
I have a table in a dataset as below
Column1 OffLoc
01/02/2016 Johannesburg
01/02/2016 Johannesburg
02/02/2016 Moscow
02/02/2016 Johannesburg
02/02/2016 Johannesburg
03/02/2016 Johannesburg
03/02/2016 Moscow
03/02/2016 Moscow
03/02/2016 Bogota
04/02/2016 Barcelona
04/02/2016 Johannesburg
04/02/2016 Singapore
04/02/2016 Singapore
04/02/2016 Singapore
05/02/2016 Singapore
05/02/2016 Singapore
05/02/2016 Singapore
10/02/2016 Singapore
10/02/2016 Singapore
10/02/2016 Singapore
10/02/2016 Singapore
10/02/2016 Singapore
I would like to have like the below
Column1 Offloc Count
01/02/2016 - Johannesburg - 2
02/02/2016 - Moscow - 1
02/02/2016 - Johannesburg - 2
03/02/2016 - Johannesburg - 1
03/02/2016 - Moscow - 2
03/02/2016 - Bogota - 1
...
I tried to use this example Linq1, but im using dataset and refrain from copying the data to a list and then performing the Tasks. I also tried following Code:
Dim oQuery = _
From oRow In ds.Table("AuditLog").AsEnumerable() _
Group By _
Column1DT = oRow("Column1"), _
OffLocDT = oRow("OffLoc") _
Into Total
But I dont know how to proceed from here. Please help me. Im using vb.net, because the online converters do not convert very well.
Thanks
You already done the grouping correctly. Next step, you can project the query into an anonymous type containing all the needed information, for example :
Dim oQuery = _
From oRow In ds.Table("AuditLog").AsEnumerable() _
Group By _
Column1DT = oRow("Column1"), _
OffLocDT = oRow("OffLoc") _
Into Total = Group
Select New With
{
Key .Column1 = Column1DT,
Key .OffLoc = OffLocDT,
.Count = G.Count()
}
Full working demo example :
Dim dt As New DataTable()
dt.Columns.Add("Column1", GetType(DateTime))
dt.Columns.Add("OffLoc", GetType(String))
dt.Rows.Add(New DateTime(2016, 1, 2), "Johannesburg")
dt.Rows.Add(New DateTime(2016, 1, 2), "Johannesburg")
dt.Rows.Add(New DateTime(2016, 1, 3), "Jakarta")
dt.Rows.Add(New DateTime(2016, 1, 3), "Jakarta")
dt.Rows.Add(New DateTime(2016, 1, 3), "Jakarta")
Dim result = From oRow In dt.AsEnumerable()
Group By
Column1DT = oRow("Column1"),
OffLocDT = oRow("OffLoc")
Into G = Group
Select New With
{
Key .Column1 = Column1DT,
Key .OffLoc = OffLocDT,
.Count = G.Count()
}
For Each item As Object In result
Console.WriteLine(item)
Next
output :
{ Column1 = 1/2/2016 12:00:00 AM, OffLoc = Johannesburg, Count = 2 }
{ Column1 = 1/3/2016 12:00:00 AM, OffLoc = Jakarta, Count = 3 }
Here You Go.
Dim list = (From g In ds.Tables("AuditLog").AsEnumerable()
Group By
col1 = g("Column1"),
col2 = g("OffLoc")
Into X = Group
Select New With
{
Key .Column1 = col1,
Key .OffLoc = col2,
.Count = X.Count()
}).ToList()
Related
I have a table like that :
dt = New DataTable()
dt.Columns.AddRange(New DataColumn() {
New DataColumn("time"),
New DataColumn("fname", Type.GetType("System.String")),
New DataColumn("note", Type.GetType("System.String")),
New DataColumn("du", Type.GetType("System.Int32")),
New DataColumn("site", Type.GetType("System.String"))})
dt.Rows.Add(New Object() {"2023-01-28 02:01", "aaa1", "xxx11xxxxxxx", 100, "a"})
dt.Rows.Add(New Object() {"2023-01-28 03:01", "bbb1", "xxxx22xxxxxx", 2, "b"})
dt.Rows.Add(New Object() {"2023-01-28 09:01", "ccc", "xxxx33xxxxxx", 3, "c"})
dt.Rows.Add(New Object() {"2023-01-28 02:01", "aaa2", "xxx44xxxxxxx", 3, "a"})
dt.Rows.Add(New Object() {"2023-01-28 03:01", "bbb2", "xxx55xxxxxxx", 53, "b"})
dt.Rows.Add(New Object() {"2023-01-28 03:01", "bbb3", "xxx66xxxxxxx", 89, "b"})
dt.Rows.Add(New Object() {"2023-01-28 01:01", "xxx", "xxx77xxxxxxx", 5, "x"})
I want to use linq to query the above table,Group by two columns time and site from a datatable, then get the fname that have maximum du I use the following code:
Dim MYquery = (From p In dt.Select()
Group p By ID = New With _
{Key .time = p("time").ToString.Trim, _
Key .site = p("site")} _
Into Group Select Group(0)).ToArray.CopyToDataTable
The result was as shown in the photo .
the desired table is :
time
fname
note
du
site
2023-01-28 02:01
aaa1
xxx11xxxxxxx
100
a
2023-01-28 03:01
bbb3
xxx55xxxxxxx
53
b
2023-01-28 09:01
ccc
xxxx33xxxxxx
3
c
2023-01-28 01:01
xxx
xxx77xxxxxxx
5
x
What should I do?
(I am a C# guy, I hope converted from C# correctly):
BTW Your sample desired output do not match what you described. It should be the row with 89 for site "b", no?
Dim myQuery = (From r In dt.Select()
Group r By ID = New With {
Key .Time = r.Field(Of String)("Time"),
Key .Site = r.Field(Of String)("Site")
} Into Group
Let mx = Group.Max(Function(gg) gg.Field(Of Integer)("Du"))
From row In Group
Where row.Field(Of Integer)("Du") = mx
Select row).CopyToDataTable()
time
fname
note
du
site
2023-01-28 02:01
aaa1
xxx11xxxxxxx
100
a
2023-01-28 03:01
bbb3
xxx66xxxxxxx
89
b
2023-01-28 09:01
ccc
xxxx33xxxxxx
3
c
2023-01-28 01:01
xxx
xxx77xxxxxxx
5
x
I Have a datatable with following records
ID NAME VALUE CONTENT
1 AAA 10 SYS, LKE
2 BBB 20 NOM
1 AAA 15 BST
3 CCC 30 DSR
2 BBB 05 EFG
I want to write a VB.NET/LINQ query to have a output like below table: -
ID NAME SUM CONTENT (as CSV)
1 AAA 25 SYS, LKE, BST
2 BBB 25 NOM, EFG
3 CCC 30 DSR
Please provide me LINQ query to get the desired result. Thanks.
I have tried concatenation using below query
Dim grouped = From row In dtTgt.AsEnumerable() _
Group row By New With {row.Field(Of Int16)("ID"), row.Field(Of String)("Name")} _
Into grp() _
Select ID, Name, CONTENT= String.Join(",", From i In grp Select i.Field(Of String)("CONTENT"))
This query will give you the expected output:-
Dim result = From row In dt.AsEnumerable()
Group row By _group = New With {Key .Id = row.Field(Of Integer)("Id"),
Key .Name = row.Field(Of String)("Name")} Into g = Group
Select New With {Key .Id = _group.Id, Key .Name = _group.Name,
Key .Sum = g.Sum(Function(x) x.Field(Of Integer)("Value")),
Key .Content = String.Join(",", g.Select(Function(x) x.Field(Of String)("Content")))}
Thanks for your answers.
However, I have managed to get the desired result using simple code (Without LINQ): -
Dim dt2 As New DataTable
dt2 = dt.Clone()
For Each dRow As DataRow In dt.Rows
Dim iID As Integer = dRow("ID")
Dim sName As String = dRow("Name")
Dim sContt As String = dRow("Content")
Dim iValue As Integer = dRow("Value")
Dim rwTgt() As DataRow = dt2.Select("ID=" & iID)
If rwTgt.Length > 0 Then
rwTgt(0)("Value") += iValue
rwTgt(0)("Content") += ", " & sContt
Else
rw = dt2.NewRow()
rw("ID") = iID
rw("Name") = sName
rw("Value") = iValue
rw("Content") = sContt
dt2.Rows.Add(rw)
End If
Next
I have a table like this:
MAName feldtext
------------------
karl fieldtext1
karl fieldtext2
karl fieldtext1
karl fieldtext3
karl fieldtext4
karl fieldtext2
karl fieldtext5
karl fieldtext3
karl fieldtext3
susi fieldtext1
susi fieldtext4
john fieldtext2
john fieldtext5
john fieldtext5
and I need:
MAName fieldtext1 fieldtext2 fieldtext3 fieldtext4 fieldtext5 FehlerJeMA
karl 2 2 3 1 1 9
susi 1 0 0 1 0 2
john 0 1 0 0 2 3
The columns fieldtext can go from fieldtext1 to fieldtextn, it's dynamic, depending on query.
I was looking here for solutions and found, so my approach:
Dim dt2 As New DataTable
Dim nn As Integer = 0
Dim Zeile As DataRow
dt2.Columns.Add("MAName")
' fieldtext distinct
Dim query2 = (From dr In (From d In newTable2.AsEnumerable Select New With {.feldtext1 = d("feldtext")}) Select dr.feldtext1 Distinct)
For Each Feldtext In query2
dt2.Columns.Add(Feldtext)
Next
column = New DataColumn()
column.DataType = System.Type.GetType("System.Int32")
column.ColumnName = "FehlerJeMA"
dt2.Columns.Add(column)
' MAName distinct
Dim query3 = (From dr In (From d In newTable2.AsEnumerable Select New With {.MAName2 = d("MAName")}) Select dr.MAName2.ToString.ToLower Distinct)
For Each Mitarbeiter In query3
Zeile = dt2.NewRow()
Zeile(0) = Mitarbeiter.ToString.ToLower
MA2 = Mitarbeiter.ToString.ToLower
nn = 1
For Each colName2 In query2
Fehler2 = colName2
Dim AnzahlFehler As String = (From row In newTable2.Rows Select row Where row("MAName").ToString.ToLower = MA2 And row("feldtext") = Fehler2).Count
If AnzahlFehler = 0 Then
AnzahlFehler = ""
End If
Zeile(nn) = AnzahlFehler
nn += 1
If AnzahlFehler <> "" Then
FehlerJeMA += CInt(AnzahlFehler)
End If
Next
Zeile(nn) = FehlerJeMA
dt2.Rows.Add(Zeile)
Next
This works, but is very slow...
It could be the case that in my table has more than 10.000 rows...
So my question is: what is fastest approach to get the result?
Is it some kind of cross table with linq? Other approaches?
In C# you will be able to use the code, try to translate it for your problem:
var pivotData = data.GroupBy(x => new {x.MAName, x.feldtext}, (key, group) => new { MAName = key.Column1, feldtext = key.Column2, count = group.Count() });
I have the following data returned from a web service and serialized into a list:
Name Severity Type
John Doe Warning A
John Doe Error A
John Doe Error A
John Doe Error A
Jane West Error B
Mike Smith Warning B
Jack Black Warning A
In vb.net, I want to summarize it into the following:
Name TypeAWarning TypeAError TypeBWarning TypeBError
John Doe 1 3
Jane West 1
Mike Smith 1
Jack Black 1
Using linq, how can I take this collection and summarize it? I tried something like:
Dim data As New List(Of TempData)
data.add(new TempData ({TypeAWarning = from d in data Group d By Name = a.Severity into Group??
I am just not sure if linq is the way to go. Can someone point me in the right direction?
Thanks!
You can use a GroupBy to group items by Name field, then knowing each group contains the key (Name field) and all items of the group, you can use this query to shape the result:
Dim Result = Items.GroupBy(Function(item) item.Name) _
.Select(Function(group) New TempData() With
{
.Name = group.Key,
.TypeAWarning = group.Where(Function(item) item.Type = "A" And item.Severity = "Warning").Count(),
.TypeAError = group.Where(Function(item) item.Type = "A" And item.Severity = "Error").Count(),
.TypeBWarning = group.Where(Function(item) item.Type = "B" And item.Severity = "Warning").Count(),
.TypeBError = group.Where(Function(item) item.Type = "B" And item.Severity = "Error").Count()
}).ToList()
I have a list of objects that is being returned from service call.
Object has below attributes:
DateVal1
DateVal2
Value
How do I assign object to range as 2D matrix range:
Date1 as column, Date2 as header row
If there is object with row,column combination print value else print NA.
Data can be large (Max 30x30) so trying to avoid lookup in list every time.
Date 1/31/2015 2/28/2015 3/31/2015
1/1/2015 1 NA NA
1/2/2015 NA 2 NA
1/3/2015 NA NA 3
What if this is slight different?
Object has below attributes:
DateVal1
DateVal2
Value1
Value2
And desired o/p is this:
Date1 Date2 110 20 30
1/1/2015 1/10/2015 1 NA NA
1/2/2015 1/20/2015 NA 2 NA
1/3/2015 1/31/2015 NA NA 3
Untested, but something like this:
Sub Test()
Dim points, i As Long, r As Long, c As Long
Dim dictRows, dictCols, grid(0, 0)
'dictionary to map "key" values to row numbers
Set dictRows = CreateObject("scripting.dictionary")
'dictionary to map "key" values to column numbers
Set dictCols = CreateObject("scripting.dictionary")
points = getPoints()
r = 0
c = 0
'[sort points by date1 here]
'map date1 to "row"
For i = LBound(points) To UBound(points)
If Not dictRows.exists(points(i).date1) Then
r = r + 1
dictRows.Add points(i).date1, r
End If
Next i
'[sort points by date2 here]
'map date2 to "column"
For i = LBound(points) To UBound(points)
If Not dictCols.exists(points(i).date2) Then
c = c + 1
dictCols.Add points(i).date2, c
End If
Next i
ReDim grid(1 To r, 1 To c)
For i = LBound(points) To UBound(points)
grid(dictRows(points(i).date1), dictCols(points(i).date2)) = points(i).Value
Next i
'populate on worksheet
With ActiveSheet
.Range("A2").Resize(r, 1).Value = Application.Transpose(dictRows.keys)
.Range("B2").Resize(r, c).Value = grid
.Range("B1").Resize(1, c).Value = dictCols.keys
End With
End Sub