Using Linq to GroupBy and Case When via datatable - c#

enter code hereI have a Datatable like this:
LN Test_Code Name Test_Item_Code Test_Data
0107001 A010 Yo V0001 1
0107001 A010 Yo V0002 2
0107001 C040 Yo V0002 1
0107001 C040 Yo V0002 2
0107002 C040 JC V0001 3
0107002 C040 JC V0002 4
0107003 C040 kk V0001 5
0107003 C040 kk V0002 6
I need to get my datatable like this:
LN Test_Code Name DueDate(V0001) DueDate2(V00002)
0107001 A010 Yo 1 2
0107001 C040 Yo 1 2
0107002 C040 JC 3 4
0107003 C040 kk 5 6
This is my SQLcommand if I can you case when.
select LN, Test_Code, Name,
case when Test_Item_Code = 'V0001' then Test_Data else '' end as DueDate(V0001),
case when Test_Item_Code = 'V0002' then Test_Data else '' end as DueDate2(V0002)
From dt Group by LN, Test_Code, Name
This is my source code now. It's still error because I don't know how to get field Test_Item_Code and Test_Data to case when.
DataTable dt = services.getData();
var data = dt.AsEnumerable()
.GroupBy(r1 => new
{LN = r1["LN"],
Test_Code = r1["Test_Code"],
Name = r1["Name"],
Test_Item_Code = r1["Test_Item_Code"],
Test_Data = r1["Test_Data"]
}).Select(g => new
{LN = g.Key.LN,
Test_Code = g.Key.Test_Code,
Name = g.Key.Name,
DueDate = g.Key.Test_Item_Code == "V0001" ? g.Key.Test_Data : "",
DueDate2 = g.Key.Test_Item_Code == "V0002" ? g.Key.Test_Data : ""
});
I got data like this from above code:
LN Test_Code Name DueDate(V0001) DueDate2(V00002)
0107001 A010 Yo 1
0107001 A010 Yo 2
0107001 C040 Yo 1
0107001 C040 Yo 2
0107002 C040 JC 3
0107002 C040 JC 4
0107003 C040 kk 5
0107003 C040 kk 6
Anyone help/advice if possible would be really appreciated. I'm very new to linq.
Solution
var data = dt.Select().GroupBy(r1 => r1["LN"])
.SelectMany(r => r.GroupBy(g => g["Test_Code"]).Select(rr =>
new
{
LN = r.Key,
Test_Code = rr.Key,
Name = rr.First()["Name"],
DueDate = rr.OrderBy(r1 => r1["Test_Item_Code"] == "V0001").First()["Test_Data"],
DueDate2 = rr.OrderBy(r1 => r1["Test_Item_Code"] == "V0002").First()["Test_Data"],
}
));

You need to Group by NL and then by Test_Code, this is an example:
var data = dt.Select().GroupBy(r1 => r1["LN"])
.SelectMany(r => r.GroupBy(g => g["Test_Code"]).Select(rr =>
new
{
LN = r.Key,
Test_Code = rr.Key,
Name = rr.First()["Name"],
DueDate = rr.FirstOrDefault(r1 => r1["Test_Item_Code"] == "V0001")["Test_Data"],
DueDate2 = rr.FirstOrDefault(r1 => r1["Test_Item_Code"] == "V0002")["Test_Data"],
}
));

Related

Query with join, group by and count to linq

im doing this query on sql and it works, but how do i make it to Linq ?
select b.Name,a.idempresa,count(1) as cuenta from Descarga_XML_recepcion_V2 as a
inner join EnterpriseSGE as b on a.idempresa = b.EnterpriseSGEId group by idempresa,b.name
this is what it should bring
name1 | 5041 | 583
name2 | 4031 | 1730
name3 | 5042 | 640
name4 | 4034 | 300
name5 | 6047 | 861
name6 | 5043 | 187
name7 | 4033 | 318
A straight forward translation of the SQL into LINQ yields:
var ans = from a in Descarga_XML_recepcion_V2
join b in EnterpriseSGE on a.idempresa equals b.EnterpriseSGEId
group 1 by new { a.idempresa, b.name } into ingroup
select new {
ingroup.Key.idempresa,
ingroup.Key.name,
cuenta = ingroup.Count()
};
Try :
var results = (from a in Descarga_XML_recepcion_V2
join b in EnterpriseSGE on a.idempresa equal b.EnterpriseSGEId
select new { a = a, b = b})
.GroupBy(x => new { idempresa = x.a.idempresa, name = x.b.name})
.Select(x => new {name = x.Key.name, idempresa = x.Key.idempressa, count = x.Count()})
.ToList();

Combine tables using row values as column LINQ C# SQL

I have a users table:
Id | Name | Age
--------------------
1 | Steve | 21
2 | Jack | 17
3 | Alice | 25
4 | Harry | 14
I also have a table containing additional user info:
UId | Key | Value
----------------------
1 | Height | 70
2 | Height | 65
2 | Eyes | Blue
4 | Height | 51
3 | Hair | Brown
1 | Eyes | Green
The UId column links to the Id column in the users table. As you can see, not all users have the same additional info present. Alice doesn't have a height value, Jack is the only one with an eye color value etc.
Is there a way to combine this data into one table dynamically using C# and LINQ queries so that the result is something like this:
Id | Name | Age | Height | Eyes | Hair
------------------------------------------
1 | Steve | 21 | 70 | Green |
2 | Jack | 17 | 65 | Blue |
3 | Alice | 25 | | | Brown
4 | Harry | 14 | 51 |
If a user does not have a value for the column, it can remain empty/null. Does this require some sort of data pivoting?
For the case, your user info fields are constant:
var result = users.GroupJoin(details,
user => user.Id,
detail => detail.Id,
(user, detail) => new
{
user.Id,
user.Name,
user.Age,
Height = detail.SingleOrDefault(x => x.Key == "Height").Value,
Eyes = detail.SingleOrDefault(x => x.Key == "Eyes").Value,
Hair = detail.SingleOrDefault(x => x.Key == "Hair").Value,
});
You can do it by utilising GroupJoin, example:
var users = new List<Tuple<int, string, int>> {
Tuple.Create(1, "Steve", 21),
Tuple.Create(2, "Jack", 17),
Tuple.Create(3, "Alice", 25),
Tuple.Create(4, "Harry", 14)
};
var userInfos = new List<Tuple<int, string, string>> {
Tuple.Create(1, "Height", "70"),
Tuple.Create(2, "Height", "65"),
Tuple.Create(2, "Eyes", "Blue"),
Tuple.Create(4, "Height", "51"),
Tuple.Create(3, "Hair", "Brown"),
Tuple.Create(1, "Eyes", "Green"),
};
var query = users.GroupJoin(userInfos,
u => u.Item1,
ui => ui.Item1,
(u, infos) => new { User = u, Infos = infos });
var result = query.Select(qi => new
{
Id = qi.User.Item1,
Name = qi.User.Item2,
Age = qi.User.Item3,
Height = qi.Infos.Where(i => i.Item2 == "Height").Select(i => i.Item3).SingleOrDefault(),
Eyes = qi.Infos.Where(i => i.Item2 == "Eyes").Select(i => i.Item3).SingleOrDefault(),
Hair = qi.Infos.Where(i => i.Item2 == "Hair").Select(i => i.Item3).SingleOrDefault()
});
First of all I have grouped the user details data using Feature (I have renamed the Key property with Feature to avoid confusion) & UId then I have used group join to combine both results using into g. Finally retrieved the result using specified feature.
var result = from user in users
join detail in details.GroupBy(x => new { x.UId, x.Feature })
on user.Id equals detail.Key.UId into g
select new
{
Id = user.Id,
Name = user.Name,
Age = user.Age,
Height = g.FirstOrDefault(z => z.Key.Feature == "Height") != null ?
g.First(z => z.Key.Feature == "Height").First().Value : String.Empty,
Eyes = g.FirstOrDefault(z => z.Key.Feature == "Eyes") != null ?
g.First(z => z.Key.Feature == "Eyes").First().Value : String.Empty,
Hair = g.FirstOrDefault(z => z.Key.Feature == "Hair") != null ?
g.First(z => z.Key.Feature == "Hair").First().Value : String.Empty,
};
I am getting following output:-
Here is the complete Working Fiddle.
Try this
var list = (from u in context.users
join ud in context.UserDetails on u.Id equals ud.UId
select new
{
u.Id,
u.Name,
u.Age,
ud.Key,
ud.Value
});
var finallist = list.GroupBy(x => new { x.Id, x.Name,x.Age}).Select(x => new
{
x.Key.Id,
x.Key.Name,
x.Key.Age,
Height = x.Where(y => y.Key == "Height").Select(y => y.Value).FirstOrDefault(),
Eyes = x.Where(y => y.Key == "Eyes").Select(y => y.Value).FirstOrDefault(),
Hair = x.Where(y => y.Key == "Hair").Select(y => y.Value).FirstOrDefault()
}).ToList();
try this query
var objlist=( form a in contex.user
join b in contex.UserDetails on a.id equals a.Uid into gj
from subpet in gj.DefaultIfEmpty()
select new { Id=a.id, Name=a.name, Age=a.age, Height =subpet.Height,Eyes=subpet.Eyes, Hair=subpet.Hair}).ToList();

Pivot Table Using Linq

I have a table like this .(VisitType is dynamic)
PersonelId VisitDate VisitTypeId
1 2015-02-24 A
2 2015-02-23 S
2 2015-02-24 D
4 2015-02-22 S
2 2015-02-22 A
2 2015-02-22 B
3 2015-02-23 A
1 2015-02-23 A
1 2015-02-24 D
4 2015-02-24 S
4 2015-02-22 S
2 2015-02-22 S
3 2015-02-24 D
I want to get a pivot of this using linq as below.
VisitDate PersonelId A S D B
2015-02-22 4 0 2 0 0
2015-02-22 2 1 1 0 0
2015-02-23 2 0 1 0 0
2015-02-23 3 1 0 0 0
2015-02-23 1 1 0 0 0
2015-02-24 1 1 0 1 0
2015-02-24 2 0 0 1 0
2015-02-24 4 0 1 0 0
2015-02-24 3 0 0 1 0
I use this linq
var d = (from f in _db.Visits
group f by new {f.VisitDate, f.PersonnelId }
into myGroup
where myGroup.Count() > 0
select new
{
myGroup.Key.VisitDate,
myGroup.Key.PersonnelId,
subject = myGroup.GroupBy(f => f.VisitTypeId).Select
(m => new { Sub = m.Count(), Score = m.Sum(c => c.Amount) })
}).ToList();
It is grouped by date and personel id, but don't count items from every VisitType.
Try this:
//static headers version
var qry = Visits.GroupBy(v=>new{v.VisitDate, v.PersonelId})
.Select(g=>new{
VisitDate = g.Key.VisitDate,
PersonelId = g.Key.PersonelId,
A = g.Where(d=>d.VisitTypeId=="A").Count(),
B = g.Where(d=>d.VisitTypeId=="B").Count(),
D = g.Where(d=>d.VisitTypeId=="D").Count(),
S = g.Where(d=>d.VisitTypeId=="S").Count()
});
//dynamic headers version
var qry = Visits.GroupBy(v=>new{v.VisitDate, v.PersonelId})
.Select(g=>new{
VisitDate = g.Key.VisitDate,
PersonelId = g.Key.PersonelId,
subject = g.GroupBy(f => f.VisitTypeId)
.Select(m => new { Sub = m.Key, Score = m.Count()})
});
first fetch your dynamic Visit Type for person like following
var VisTyp= (from VT in _db.VisitType select new{VisType=VT.VisitType} ).ToList();
then use following.
var d = (from f in _db.Visits
group f by new {f.VisitDate, f.PersonnelId } into myGroup
where myGroup.Count() > 0
select new
{
VisitDate = myGroup.Key.VisitDate,
PersonnelId = myGroup.Key.PersonnelId,
subject=myGroup.Count(t => VisTyp.Contains(t.VisitType))
}).ToList();

Linq involving groupby orderby and join

I have two tables
tblEquipment
Id1 Id2 Version1 Version2
1 1 - 0
2 1 A 1
3 1 B 1
4 1 B 2
5 2 - 0
6 2 A 0
and another table
tblHistory
IdParent Version1 Version2 Date
1 - 0 1/01/14
1 A 1 2/01/14
1 B 1 3/01/14
1 B 2 4/01/14
2 - 0 4/01/14
2 A 0 6/01/14
2 A 0 8/01/14
I am trying to write a query that fetches the record which has the maximum Version1 and Version2 corresponding to the maximum version1. For e.g. I want the following records from the above table -
Id2 = 1, Version1 = B, Version2 = 2 and Date = 4/01/14
Id2 = 2, Version1 = A, Version2 = 0 and Date = 8/01/14
Can anyone help me with the linq that gives me the above result.
Fetching data according the rule you described would be like this:
var result = history
.GroupBy( h => h.IdParent )
.Select( h => h.OrderBy( h1 => h1.Version1 )
.ThenBy( h2 => h2.Version2 )
.Last() )
.Select(h => new {
Id2 = h.IdParent,
Version1 = h.Version1,
Version2 = h.Version2,
Date = h.Date
}
);

Cannot use id on column title when pivoting and colum values are mixed

In this query:
select *
from
(
select distinct a.id as 'Id Documento',
b.valor, 'index'+cast(row_number() over(partition by a.id order by b.idIndice) as varchar(10)) rn
from tgpwebged.dbo.sistema_Documentos as a
join tgpwebged.dbo.sistema_Indexacao as b on a.id = b.idDocumento
join tgpwebged.dbo.sistema_DocType as c on a.idDocType = c.id
join tgpwebged.dbo.sistema_DocType_Index as d on c.id = d.docTypeId
where d.docTypeId = 40
and (b.idIndice = 11 AND b.valor = '11111111' OR b.idIndice = 12 AND b.valor = '11111')
) src
pivot
(
max(valor)
for rn in (Index1, Index2)
) piv
How to add the value of b.idIndice in the 2 pivoted columns?
I have this:
id Documento Index1 Index2
I need
id Documento 11 12
Second. I am getting
Id Documento Index1 Index2
13 11111111 11111111
14 11111111 11111111
16 11111 11111
It is mixing the values... the value '11111111' should be on Index1 column and '11111' should be on Index2 columns.
What can I do?

Categories

Resources