How to count group of records using LINQ Query? - vb.net

I have a database table that have a structure like this:
ID Integer Auto Incresement
Name VarChar
Status VarChar
Sample records:
ID Name Status
1 record 1 Outstanding
2 record 2 Outstanding
3 record 3 Aging
4 record 4 Outstanding
5 record 5 Aging
6 record 6 Outstanding
In the table, there are two main status: "Outstanding" and "Aging". I want to count how many records with status of "Outstanding" and how many records with status of "Aging" available in the table.
This is a sample LINQ Query:
Using DC = DataClassesDataContext.Create()
Dim dataTable = From Count(Outstanding), Count(Aging) In DC.MyTable _
Where item.Status = "Outstanding" OrElse item.Status = "Aging" _
Group By item.Status _
Select item
End Using
The expected result should be:
Outstanding Aging
4 2
Can you help me to design a LINQ to achive the result?

Try this:
Dim MyTable = { _
New With {.ID = 1, .Name = "record 1", .Status = "Outstanding"},
New With {.ID = 2, .Name = "record 2", .Status = "Outstanding"},
New With {.ID = 3, .Name = "record 3", .Status = "Aging"},
New With {.ID = 4, .Name = "record 4", .Status = "Outstanding"},
New With {.ID = 5, .Name = "record 5", .Status = "Aging"},
New With {.ID = 6, .Name = "record 6", .Status = "Outstanding"}
}
Dim dataTable = _
From item In MyTable
Group By Key = item.Status Into Xs = Group
Select New With {.Status = Key, .Count = Xs.Count()}
I get this result:

Try this :-
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var test = new List<Sample>();
test.Add(new Sample{ID=1,Name="record 1",Status="Outstanding"});
test.Add(new Sample{ID=2,Name="record 2",Status="Outstanding"});
test.Add(new Sample{ID=3,Name="record 3",Status="Aging"});
test.Add(new Sample{ID=4,Name="record 4",Status="Outstanding"});
test.Add(new Sample{ID=5,Name="record 5",Status="Outstanding"});
test.Add(new Sample{ID=6,Name="record 6",Status="Aging"});
var result = from row in test
group row by "Count" into g
where g.FirstOrDefault() != null
select new
{
//Status = g.Key,
Outstanding = g.Where(C => C.Status == "Outstanding").Count(),
Aging = g.Where(C => C.Status == "Aging").Count()
};
Console.WriteLine("Outstanding"+" "+"Aging");
foreach(var item in result)
{
Console.WriteLine(" "+item.Outstanding+" "+item.Aging);
}
}
}
public class Sample
{
public int ID {get;set;}
public string Name {get;set;}
public string Status {get; set;}
}
result :-
you can run above sample code using following link - https://dotnetfiddle.net/xC2NXm
suggest improvement :)

Related

Find rank of user by LINQ

enter image description here
How can I get Rank of a user in table by LINQ ? I use VB.NET CODE
if we have these fields in our table
[id , name , score]
after order by score of users how we can get the ranking ( row number ) one of them in our query ?
Thank you man . I used the bellow code and it's work fine for me:
Dim query = (From P In DB.tblUserScores Order By P.Score
Descending Select P).AsEnumerable()
Dim Rank As Integer = 1
For Each userObj As tblUserScore In query
If userObj.DeviceId = DeviceID Then Exit For
Rank += 1
Next
Here's how:
Dim records = _
{ _
New With { Key .ID = 1, Key .Name = "A1", Key .Score = 7 }, _
New With { Key .ID = 2, Key .Name = "A2", Key .Score = 9 }, _
New With { Key .ID = 3, Key .Name = "A3", Key .Score = 2 }, _
New With { Key .ID = 4, Key .Name = "A4", Key .Score = 1 }, _
New With { Key .ID = 5, Key .Name = "A5", Key .Score = 6 }, _
New With { Key .ID = 6, Key .Name = "A6", Key .Score = 4 }, _
New With { Key .ID = 7, Key .Name = "A7", Key .Score = 7 }, _
New With { Key .ID = 8, Key .Name = "A8", Key .Score = 3 }, _
New With { Key .ID = 9, Key .Name = "A9", Key .Score = 5 }, _
New With { Key .ID = 10, Key .Name = "A10", Key .Score = 8 } _
}
Dim query = _
From r In Records _
Order By r.Name Ascending
Order By r.Score Descending
Select r
query.Dump()
Dim rank = _
query _
.Select(Function (x, n) New With { Key .Record = x, Key .Rank = n + 1 }) _
.ToDictionary(Function (x) x.Record.Name, Function (x) x.Rank)
Dim name = "A9"
Console.WriteLine("User " & name & "'s Rank is " & rank(name))
That gives me:
User A9's Rank is 6

Putting my code into a nested loop

Can anyone help me put this code into a nested loop please. It is a code to calculate the lowest score of candidates who have been ranked in order of preferences with 1 being the first preference and 5 being the highest.
Dim min = 0
If Candidate1total > min Then
min = Candidate1total
LabelWINNER.Text = EnterNames.Cand1Name.Text
End If
If Candidate2total < min Then
min = Candidate2total
LabelWINNER.Text = EnterNames.Cand2Name.Text
End If
If Candidate3total < min Then
min = Candidate3total
LabelWINNER.Text = EnterNames.Cand3Name.Text
End If
If Candidate4total < min Then
min = Candidate4total
LabelWINNER.Text = EnterNames.Cand4Name.Text
End If
If candidate5total < min Then
min = candidate5total
LabelWINNER.Text = EnterNames.Cand5Name.Text
End If
Candidate1Total to Candidate5Total are the total scores for the candidates. This is calculated by working out the number of times a user has voted for them. The name that the candidate was given on the ENTERNAMES form is then placed in the labelWINNER if that candidate is lower then the minuim.
I think it would be something like for 0 in candidate1 total, im not 100% certain, hence asking for help.
This is what I would do:
Dim Candidates = _
{ _
New With { .Candidate = EnterNames.Cand1Name.Text, .Total = Candidate1total }, _
New With { .Candidate = EnterNames.Cand2Name.Text, .Total = Candidate2total }, _
New With { .Candidate = EnterNames.Cand3Name.Text, .Total = Candidate3total }, _
New With { .Candidate = EnterNames.Cand4Name.Text, .Total = Candidate4total }, _
New With { .Candidate = EnterNames.Cand5Name.Text, .Total = Candidate5total } _
}
Dim result = _
Candidates _
.OrderBy(Function (c) c.Total) _
.GroupBy(Function (c) c.Total, Function (c) c.Candidate) _
.Select(Function (c) New With { .Candidate = String.Join(", ", c), .Total = c.Key }) _
.First()
So, to see the result, I used this example data:
Dim Candidates = _
{ _
New With { .Candidate = "Mike", .Total = 5 }, _
New With { .Candidate = "Tony", .Total = 2 }, _
New With { .Candidate = "Bill", .Total = 2 }, _
New With { .Candidate = "Carl", .Total = 3 }, _
New With { .Candidate = "Dick", .Total = 4 } _
}
I got this result:
Of course, if it were just one candidate with the lowest total score then there would only be one name in the Candidate field.

objectdb select where query

I attempt to select some instance using where clause
public static List<RSSItem> getRSSItem(int x1, int x2) {
EntityManagerFactory emf = DBHandler.getEmf();
EntityManager em = DBHandler.getEm(emf);
String query =
"SELECT items FROM RSSItem items "
+ "WHERE items.id <= :x1 AND "
+ "items.id >= :x2";
List<RSSItem> results =
(List<RSSItem>) em.createQuery(query).
setParameter("x1", x1).
setParameter("x2", x2).
getResultList();
return results;
}
the RSSItem attributes :
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
String title;
String link;
String description;
String pubdate;
String content;
HashMap<String, Integer> keyword = new HashMap();
HashMap<String, Integer> keywordBefore = new HashMap();
// TreeMap <String, Integer> keyword = new TreeMap();
String feed;
the problem is it always return a list with 0 size. what's wrong with my select query?
With the values x1 = 1 and x2 = 500, the query turns into...
SELECT items FROM RSSItem items
WHERE items.id <= 1
AND items.id >= 500
Since no id's are less or equal to 1 and greater or equal to 500 at the same time, the query will give no hits. What you want is probably;
String query =
"SELECT items FROM RSSItem items "
+ "WHERE items.id >= :x1 AND "
+ "items.id <= :x2";
...which with your example data will find all id's between 1 and 500, inclusive.

VB.NET LINQ - Matching Hierarchical Data to Flat Data

I have 2 representations of similar data from 2 different systems and I need to match each entity in one system with the entities in the other.
System A is Hierarchical, represented as a Dictionary(Of String, List(Of CategoryA)) looking something like:
- "Organization 1"
- { Name = "Cat1", Id = 1}
- { Name = "Cat2", Id = 2}
- { Name = "Cat3", Id = 3}
- "Organization 2"
- { Name = "Cat1", Id = 4}
- { Name = "Cat3", Id = 5}
- { Name = "Cat4", Id = 6}
- "Organization 3"
- { Name = "Cat1", Id = 7}
- { Name = "Cat2", Id = 8}
- { Name = "Cat3", Id = 9}
- { Name = "Cat4", Id = 10}
System B is Flattened, represented as a List(Of CategoryB) looking something like:
- { Org = "Organization 1", Name = "Cat1", Id = 100 }
- { Org = "Organization 1", Name = "Cat2", Id = 101 }
- { Org = "Organization 1", Name = "Cat3", Id = 102 }
- { Org = "Organization 2", Name = "Cat1", Id = 103 }
- { Org = "Organization 2", Name = "Cat2", Id = 104 }
- { Org = "Organization 2", Name = "Cat4", Id = 105 }
- { Org = "Organization 4", Name = "Cat1", Id = 106 }
- { Org = "Organization 4", Name = "Cat2", Id = 107 }
- { Org = "Organization 4", Name = "Cat3", Id = 108 }
- { Org = "Organization 4", Name = "Cat4", Id = 109 }
And basically what I need to do is to outer join the hierarchical data to the flattened data on Organization name (Dictionary.Key to CategoryB.Org) and Category Name (CategoryA.Name to CategoryB.Name), leaving me with a Dictionary(Of String, IEnumerable(Of Tuple(Of CategoryA, CategoryB))) or something that looks something like:
- "Organization 1"
- { Name = "Cat1", Id = 1}, { Org = "Organization 1", Name = "Cat1", Id = 100 }
- { Name = "Cat2", Id = 2}, { Org = "Organization 1", Name = "Cat2", Id = 101 }
- { Name = "Cat3", Id = 3}, { Org = "Organization 1", Name = "Cat3", Id = 102 }
- "Organization 2"
- { Name = "Cat1", Id = 4}, { Org = "Organization 2", Name = "Cat1", Id = 103 }
- { Name = "Cat3", Id = 5}, null
- { Name = "Cat4", Id = 6}, { Org = "Organization 2", Name = "Cat4", Id = 105 }
- "Organization 3"
- { Name = "Cat1", Id = 7}, null
- { Name = "Cat2", Id = 8}, null
- { Name = "Cat3", Id = 9}, null
- { Name = "Cat4", Id = 10}, null
I don't have access to the CategoryA object to be able to apply an Organization property to it, or I would do it and make this easier on myself. I just can't figure out how to join on the Dictionary key and a property of one of the items in its value, and end up with anything useful. The most successful implementation I've created involves a For Each loop first, and a LINQ query inside:
Given:
catA = Dictionary(Of String, List(Of CategoryA))
catB = List(Of CategoryB)
Dim result As New Dictionary(Of String, List(Of Tuple(Of CategoryA, CategoryB)))
For Each kvp As KeyValuePair(Of String, List(Of CategoryA)) In catA
Dim orgName As String = kvp.Key
If Not result.ContainsKey(orgName) Then
result.Add(orgName, New List(Of Tuple(Of CategoryA, CategoryB)))
End If
Dim orgCategories As IEnumerable(Of CategoryB) =
From cat In catB Where cat.Org = orgName
Dim tmpResult As IEnumerable(Of Tuple(Of CategoryA, CategoryB)) =
From cat_a In kvp.Value
Group Join cat_b In orgCategories
On cat_a.Name Equals cat_b.Name
Into matchedCats = Group
From cat In matchedCats.DefaultIfEmpty
Select matches = Tuple.Create(cat_a, cat)
result(orgName).AddRange(tmpResult)
Next
It works alright, but I'd like it to be in the same statement.
Well, this kinda works but id stick with your for loop!
Public Class CategoryA
Public Property Name As String
Public Property Id As Integer
End Class
Public Class CategoryB
Public Property Org As String
Public Property Name As String
Public Property Id As Integer
End Class
Private SystemA As New Dictionary(Of String, List(Of CategoryA))
Private SystemB As New List(Of CategoryB)
Sub Main()
SystemA.Add("Org1", New List(Of CategoryA) From {New CategoryA() With {.Id = 1, .Name = "Cat1"},
New CategoryA() With {.Id = 2, .Name = "Cat2"},
New CategoryA() With {.Id = 3, .Name = "Cat3"}})
SystemA.Add("Org2", New List(Of CategoryA) From {New CategoryA() With {.Id = 4, .Name = "Cat1"},
New CategoryA() With {.Id = 5, .Name = "Cat2"},
New CategoryA() With {.Id = 6, .Name = "Cat3"}})
SystemA.Add("Org3", New List(Of CategoryA) From {New CategoryA() With {.Id = 7, .Name = "Cat1"},
New CategoryA() With {.Id = 8, .Name = "Cat2"},
New CategoryA() With {.Id = 9, .Name = "Cat3"},
New CategoryA() With {.Id = 10, .Name = "Cat4"}})
SystemB.Add(New CategoryB() With {.Org = "Org1", .Name = "Cat1", .Id = 100})
SystemB.Add(New CategoryB() With {.Org = "Org1", .Name = "Cat2", .Id = 101})
SystemB.Add(New CategoryB() With {.Org = "Org1", .Name = "Cat3", .Id = 102})
SystemB.Add(New CategoryB() With {.Org = "Org2", .Name = "Cat1", .Id = 103})
SystemB.Add(New CategoryB() With {.Org = "Org2", .Name = "Cat2", .Id = 104})
SystemB.Add(New CategoryB() With {.Org = "Org2", .Name = "Cat4", .Id = 105})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat1", .Id = 106})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat2", .Id = 107})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat3", .Id = 108})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat4", .Id = 109})
Dim AllOrgs = SystemA.Keys.Union(SystemB.Select(Function(b) b.Org).Distinct)
Dim BothCats2 = From org In AllOrgs
Let CatAList = If(Not SystemA.ContainsKey(org), New List(Of CategoryA), From cat In SystemA(org))
Let CatBList = (From cat In SystemB Where cat.Org = org).ToList
Let AllCatNames = (From cat In CatAList Select cat.Name Distinct).Union(From cat In CatBList Select cat.Name Distinct)
Let BothCats = (From cat In AllCatNames
From A In CatAList.Where(Function(CatA) CatA.Name = cat).DefaultIfEmpty
From B In CatBList.Where(Function(CatB) CatB.Name = cat).DefaultIfEmpty)
Select org, BothCats
End Sub

LINQ - querying top 5 with rank number

How do I return a top 5 with rank number using linq?
Dim Top5 = From A In DAO.Cache.Select(Of VO.Empresa).Take(5) Select A.Nome
I would like this result:
Rank Name
1 "Example Name"
2 "Example Name"
3 "Example Name"
4 "Example Name"
5 "Example Name"
You need to use the Select overload which provides the index:
Dim Top5 = DAO.Cache.Take(5).Select(Function(A, Index) New With { .Rank = Index, .Name = A.Nome })
(I kept the property spelling .Nome - though I suspect it may need to be .Name)
If grdDetail.RowCount < 10 Then
grdDetail.CurrentRow.Cells(OrderNo.Name).Value = "00" & grdDetail.RowCount
ElseIf grdDetail.RowCount > 10 And grdDetail.RowCount < 100 Then
grdDetail.CurrentRow.Cells(OrderNo.Name).Value = "0" & grdDetail.RowCount
Else
grdDetail.CurrentRow.Cells(OrderNo.Name).Value = grdDetail.RowCount
End If
I'm not entirely sure I understand your question entirely: but I'm assuming you want to order your list to produce the top 5 in Rank - ascending order?
You can quite easily do this with the built in LINQ ordering syntax:
VB:
Dim Top5 = From o in objects Order By o.Rank Ascending Select o
C#: var top5 = from o in objects orderby o.Rank ascending select o
(surprising similar in this case /giggle)
For example, you could do the following:
C#:
void Main()
{
List<MyObject> objs = new List<MyObject>();
objs.Add(new MyObject{ Rank = 1, Message = "NUMBER ONE"});
objs.Add(new MyObject{ Rank = 3, Message = "NUMBER THREE"});
objs.Add(new MyObject{ Rank = 5, Message = "NUMBER FIVE"});
objs.Add(new MyObject{ Rank = 4, Message = "NUMBER FOUR"});
objs.Add(new MyObject{ Rank = 2, Message = "NUMBER TWO"});
var sortedobjs = from o in objs
orderby o.Rank ascending
select o;
Console.WriteLine(sortedobjs.ToList());
}
public class MyObject
{
public int Rank {get; set;}
public string Message {get; set;}
}
Which would spit out:
Rank Message
1 NUMBER ONE
2 NUMBER TWO
3 NUMBER THREE
4 NUMBER FOUR
5 NUMBER FIVE
HTH.