Merging two tables and concatenating the values using linq - c#

My table data looks like:
table 1:
Id CId Message
1 1 E:MMM
1 1 E:NNN
1 1 E:OOO
1 2 E:PPP
1 2 E:PPP
table 2:
Id CId Message
1 1 W:NNN
1 1 W:OOO
After merging two tables using linq my output table should be like:
Result table:
Id CId ErMessage WrMessage
1 1 E:MMM*E:NNN*E:OOO W:NNN*W.OOO
1 2 E:PPP*E:PPP
Please help me how to achieve.

var q =
from t1 in
table1.GroupBy(g => g.ID).Select(g => new
{
ID = g.Key,
Message = string.Join("*", g.Select(v => v.Message).ToArray())
})
join
t2 in
table2.GroupBy(g => g.ID).Select(g => new
{
ID = g.Key,
Message = string.Join("*", g.Select(v => v.Message).ToArray())
}) on t1.ID equals t2.ID
select new
{
ID = t1.ID,
ErMessage = t1.Message,
WrMessage = t2.Message
};

Related

linq group by two columns and get only rows with same group by values

I want to retrieve data by group two columns ( Parent_Id and Name ) using LINQ and get the result only the rows with the same group by values.
Child
---------
Id Parent_Id Name
1 1 c1
2 1 c2
3 2 c1 <-----
4 2 c1 <-----
5 3 c2
6 3 c3
7 4 c4 <-----
As you can see, for Parent_Id 1 and 2, Name are different. So, I don't what those rows.
The result I want is like
Parent_Id Name
2 c1
4 c4
What I have tried is
from c in Child
group c by new
{
c.Parent_Id,
c.Name
} into gcs
select new Child_Model()
{
Parent_Id = gcs.Key.Parent_Id,
Name= gcs.Key.Name
};
But it return all rows.
As you describe it you should group by Parent_id only and get the groups that have distinct Names:
var result = children
.GroupBy(c => c.Parent_Id)
.Where(g => g.Select(t => t.Name).Distinct().Count() == 1)
.Select(g => new
{
Parent_Id = g.Key,
Name = g.Select(c => c.Name).First()
});
Reduced to final edit as per Gert Arnold's request:
var result = from r in (from c in children
where !children.Any(cc => cc.Id != c.Id &&
cc.Parent_Id == c.Parent_Id &&
cc.Name != c.Name)
select new {
Parent_Id = c.Parent_Id,
Name = c.Name
}).Distinct().ToList()
select new Child_Model
{
Parent_Id = r.Parent_Id,
Name = r.Name
};
var myModel = Child.GroupBy( c => $"{c.Parent_Id}|{c.Name}",
(k, list) => new Child_Model{
Parent_Id = list.First().Parent_Id,
Name = list.First().Parent_Id,
Count = list.Count()})
.Max (cm => cm.Count);
You can add a condition to filter result (groupName.Count() > 1):
from c in childs
group c by new { c.Parent_Id, c.Name } into gcs
where gcs.Count() > 1
select new { gcs.Key.Parent_Id, gcs.Key.Name }

return 0 for items count in linq statement

Lets say I have the following EF6 Linq statement which counts number of items for 2 tables (Table1 has 10 items and Table2 has no items) :
var q = db.Table1.GroupBy(g => "Table1").Select(g => new { Name = g.Key, EntryCount = g.Count() })
.Union(db.Table2.GroupBy(g => "Table2").Select(g => new { Name = g.Key, EntryCount = g.Count() }));
var r = q.ToList();
The expected result should be something like
Name | EntryCount
---------------------
Table1 | 10
Table2 | 0
However because Table2 doesn't have any items it doesn't appear in the final result and I get the following:
Name | EntryCount
---------------------
Table1 | 10
How can I make sure Table 2 always appear in the final list even if its empty and doesn't have any records?
To give you a background on why I am doing this Linq statement , I am converting the following TSQL statement into a linq query:
CREATE FUNCTION [dbo].[ufnGetLookups] ()
RETURNS
#lookupsWithItemCounts TABLE
(
[Name] VARCHAR(100),
[EntryCount] INT
)
AS
BEGIN
INSERT INTO #lookupsWithItemCounts([Name],[EntryCount])
VALUES
('Table1', (SELECT COUNT(*) FROM Table1)),
('Table2', (SELECT COUNT(*) FROM Table2)),
('Table3', (SELECT COUNT(*) FROM Table3))
RETURN;
END
Also its very important to for this linq statement to run in one database trip, not multiple.
If you have a list of tables then table list can be used to union a row with EntryCount = 0 and then on final result set a GroupBy on Name and Sum of EntryCount will provide desired result.
//List of tables
var tableList = new string[] { "Table1", "Table2" };
var res = db.Table1
.GroupBy(t1 => "Table1")
.Select(gt1 => new { Name = gt1.Key, EntryCount = gt1.Count()})
.Union(db.Table2
.GroupBy(t2 => "Table2")
.Select(gt2 => new { Name = gt2.Key, EntryCount = gt2.Count()})
)
.Union(tableList
.GroupBy(s => s)
.Select(gs => new { Name = gs.Key, EntryCount = 0 })
)
.GroupBy(gg => gg.Name)
.Select(fg => new {Name = fg.Key, EntryCount=fg.Select(ee => ee.EntryCount).Sum()})
.ToList();
The result will have EntryCount for all tables in list.
You can do this by creating a default table with a single row in it.
var ans = Table1.GroupBy(u => "Table1")
.Select(ug => new { Name = ug.Key, EntryCount = ug.Count() })
.Union(Table2.GroupBy(l => "Table2")
.Select(lg => new { Name = lg.Key, EntryCount = lg.Count() })
.Union(OneRowTable.GroupBy(u2 => 1)
.Select(u2g => new { Name = "Table2", EntryCount = u2g.Count()-1 }) )
.OrderByDescending(cg => cg.EntryCount)
.Take(1)
);
This is evaluated in a single round trip to the database by LINQ to SQL. I can't easily test with LINQ to EF.
Note that in EF Core 3.0, the original query is translated in such a way as to return a 0 row for any empty tables.

Linq query join one table row to another table multiple row

Table name: Namelist
id | Name
------------
1 |xxxxx
2 |yyyyy
Table name: Category
id | Nameid |Categoryid
-----------------
1 |1 |5
2 |1 |4
3 |2 |3
4 |2 |8
I need a linq query result like this
id | Name |Categoryid
-----------------
1 |xxxx |5,4
2 |yyyy |3,8
I tried below linq but it displays first category id only
var list = from n in namelist
join c in category on n.id equals c.nameid
select new
{
n.id,
n.name,
c.categoryid
}
You can do this with Group Join and join all the category id's in the group with String.Join like this:-
var result = (from n in namelist
join c in categories
on n.Id equals c.NameId into g
select new
{
id = n.Id,
Name = n.Name,
CategorieIds = g.Select(x => x.CategoryId)
}).AsEnumerable()
.Select(x => new
{
Id = x.id,
Name = x.Name,
CategoryIds = String.Join(",",x.CategorieIds))
});
You can try String.Join:
var list = namelist
.Select(n => new {
n.id,
n.name,
categoryids = String.Join(",", category
.Where(c => c.nameid == n.id)
.Select(c => c.categoryid))
});
Use String.Join(). I modified your statement:
var list = from n in namelist
join c in category on n.id equals c.nameid
group g by new { n.id, n.name }
select new
{
id = g.Key.id,
Name = g.Key.name,
Categoryid = String.Join(",", g.Select(x => x.c.categoryid))
}
First you take a join on NameList and Category table and then bring them into objects using ToList or AsEnumerable methods like
var list = (from n in db.NameList
join c in db.Category on n.id equals c.nameid
select new
{
id = n.id,
Name = n.name,
Categoryid = c.id
}).ToList();
var list2 = from l in list
group by new {l.id, l.Name} into groupings
from g in groupings select new{
g.Key.id,
g.Key.Name,
CategoryId = string.Joing(",", groupings.Where(x=>x.NameId == g.Key.id).Select(y=>y.CategoryId))
};
The benefit of using ToList for fetching data from db is that you will only one query in database and all required records are fetched in the memory. The second statement will group those records by id and Name and will apply string.Join on CategoryId. Please note that if you use string.join method on Linq-to-Entities query, it will fail because this method cannot be converted into sql expression.

LINQ to SQL: Group, Count, Sum. I'm so confused

Good morning all,
I have been stuck on this all morning and feel like I've hit a wall. I'd love any advice that can be given at this point.
My table is basically as follows:
PatientName|LivingSpace
-----------|-----------
Patient 1 | Unit 1
Patient 2 | Unit 1
Patient 3 | Unit 2
Patient 4 | Unit 2
Patient 5 | Unit 3
Patient 6 | Unit 3
Patient 7 | Unit 3
Patient 8 | Unit 3
I need a LINQ to SQL query to illustrate this:
Unit|Count
----|-----
Unit 1 | 2
Unit 2 | 2
Unit 3 | 4
TOTAL | 8
My SQL query works fine, I'm just having issues with converting it to LINQ:
SELECT LivingSpace, COUNT(LivingSpace) AS LivingSpace
FROM PatientTable
WHERE Status = 'Active'
GROUP BY LivingSpace
UNION ALL
SELECT 'SUM' LivingSpace, COUNT(LivingSpace)
FROM PatientTable
var counts = from x in ctx.PatientTable
group x by x.LivingSpace into y
select new { Key = y.Key Count = y.Count() };
var total = new { Key = "Total" , Count = ctx.PatientTable.Count() };
var full = counts.ToList();
full.Add(total);
If you want to do it all in one query the following should work (adjusting for the actual names of your properties of course).
context.PatientTable.GroupBy(a => a.LivingSpace.Name, a => 1)
.Select(a => new
{
a.Key,
Total = a.Sum(q => q)
})
.Union(PatientTable.Select(a => new
{
Key = "Total",
Total = PatientTable.Count()
}))
var report = patients
.GroupBy(p => p.LivingSpace)
.Select(g => new
{
Unit = g.Key,
Count = g.Count()
})
.Union(patients
.Select(p => new
{
Unit = "Total",
Count = patients.Count
}));
Something like this should work and just run one query.
var results = db.PatientTable
.GroupBy(p => p.LivingSpace)
.Select(grp => new
{
Unit = grp.Key,
Count = grp.Count()
})
.Union(db.PatientTable
.GroupBy(p => 1)
.Select(grp => new
{
Unit = "Total",
Count = grp.Count()
}));
I see you got the answer, but for learning purposes, here is side by side conversion.
Your SQL (with some aliases added for better comparison)
SELECT P.LivingSpace, COUNT(P.*) AS Count
FROM PatientTable AS P
WHERE P.Status = 'Active'
GROUP BY P.LivingSpace
UNION ALL
SELECT 'SUM' AS LivingSpace, COUNT(P.*) AS Count
FROM PatientTable AS P
The same single query in LINQ
var query =
(
from p in db.PatientTable
where p.Status = "Active"
group p by p.LivingSpace into g
select new { LivingSpace = g.Key, Count = g.Count() }
)
.Concat
(
from p in db.PatientTable
group p by "SUM" into g
select new { LivingSpace = g.Key, Count = g.Count() }
);

Distinct with group by in Linq

ID UserName BookType BookID
1 Krish 1 1
1 Krish 1 2
1 Krish 2 1
1 Krish 2 2
2 Ram 1 1
3 Raj 1 1
3 Raj 1 2
I have above table and I want to get the distinct BookType count and BookID count for each user, I am able to write this in SQL Server but when I come to LINQ I am unable to write the query.
I need the following output
ID UserName BookType BookID
1 Krish 2 2
2 Ram 1 1
3 Raj 1 2
This should give you correct result:-
var result = Userlist.GroupBy(x => new { x.ID, x.UserName })
.Select(x => new
{
ID = x.Key.ID,
UserName = x.Key.UserName,
BookType = x.Max(z => z.BookType),
BookId = x.Max(z => z.BookId)
});
Update:
Although you agreed to answer, I somehow missed your requirement and the answer which I posted above is wrong since it fetch the maximum BookType & BookId. Below is the query to fetch the distinct count:-
var result = Userlist.GroupBy(x => new { x.ID, x.UserName })
.Select(x => new
{
ID = x.Key.ID,
UserName = x.Key.UserName,
BookType = x.Select(z => z.BookType).Distinct().Count(),
BookId = x.Select(z => z.BookId).Distinct().Count()
});

Categories