How can I join two tables to get the following results in the pictures below? I want to get the counts of the project names.
I know I can group by Project ID:
var TotalSupportsByProject =
from s in db.MySupportContext
.GroupBy(s => s.ProjectID)
.Select(g => new { ProjectId = g.Key, Total = g.Count() })
select s;
Join and group. It appears you are trying to get the counts of support for each of the projects.
var query =
from s in db.Support
join p in db.Project on s.ProjectId equals p.ProjectId
group 1 by p.ProjectName into g
select new
{
ProjectName = g.Key,
TotalSupport = g.Count(),
};
If you need to be able to include counts of projects with no support, some adjustments would have to be made. Assuming the Project table contains a all of the projects you need:
var query =
from p in db.Project
select new
{
p.ProjectName,
TotalSupport = db.Support.Count(s => s.ProjectId == p.ProjectId),
};
Related
I have two tables:
PractitionerSkill { Id, Title }
PractitionerInSkills { Id, PractitionerSkillId ), where PractitionerSkillId is FK into PractitionerSkill
(there are more columns but that is not really important)
And I'm trying to count number of skills pr practitioner.
Using LINQ method syntax, I am trying to do this:
SELECT
S.Id, S.Title, COUNT(*) as [Count] from
PractitionerSkills S INNER JOIN
PractitionerInskills PIS ON S.ID = PIS.PractitionerSkillId
GROUP BY
S.Id, S.Title
ORDER BY
S.Title
Easy in SQL. Notice that I'm getting the ID, title and count in the result.
My current efforts (which is not even method syntax)
var query = from skill in _context.PractitionerSkills
join pis in _context.PractitionerInSkills on skill.Id equals pis.PractitionerSkillId into grp
select new
{
Title = skill.Title,
Count = grp.Count()
};
which is almost there, but I can't get more columns out. I need the Skill.Id (or PractitionerInSkills.PractitionerSkillId)
It's easy in Linq too!
var query = _context.PractitionerSkills.Join(_context.PractitionerInSkills,
ps => new { k1 = ps.Id },
pis => new { k1 = pis.PractitionerSkillId },
(ps, pis) => new { ps.Id, ps.Title })
.GroupBy(r => new { r.Id, r.Title })
.Select(g => new { g.Key.Id, g.Key.Title, Count = g.Count() })
.OrderBy(r => r.Title);
I've been stuck with this problem for a few days now.
How do I group by PartCode, take the Max/Min or First value of the Description (items with the same partcode may have a different description), and then sum of the other fields. What I currently have is shown below:
var lengths =
from q in
(from p in partList
select new { p.PartCode, p.Description, p.Quantity, p.TotalMeter, p.PurchaseLength })
group q by new { q.PartCode, q.Description, q.Quantity, q.TotalMeter, q.PurchaseLength } into g
orderby g.Key.PartCode
select new
{
PartCode = g.Max(p => p.PartCode),
Description = g.Max(p => p.Description),
Quantity = g.Sum(p => p.Quantity),
TotalMeter = g.Sum(p => p.TotalMeter),
PurchaseLength = g.Sum(p => p.PurchaseLength)
};
I see two main problems here:
The first is that you say you want to group by PartCode, but instead you're grouping by a combination of everything.
Another possible problem is that you're using Max() on what I can only assume to be collections of strings. This won't fail, but it will select the value that is last in alphabetical order (is that what you want?).
Try this:
var lengths =
from q in
(from p in partList
select new { p.PartCode, p.Description, p.Quantity,
p.TotalMeter, p.PurchaseLength })
group q by q.PartCode into g
orderby g.Key
select new
{
PartCode = g.First().PartCode,
Description = g.First().Description,
Quantity = g.Sum(p => p.Quantity),
TotalMeter = g.Sum(p => p.TotalMeter),
PurchaseLength = g.Sum(p => p.PurchaseLength)
};
If that doesn't solve your issue please tell us what your issue is.
I have a simple LINQ lambda join query but I want to add a 3rd join with a where clause. How do I go about doing that?
Here's my single join query:
var myList = Companies
.Join(
Sectors,
comp => comp.Sector_code,
sect => sect.Sector_code,
(comp, sect) => new {Company = comp, Sector = sect} )
.Select( c => new {
c.Company.Equity_cusip,
c.Company.Company_name,
c.Company.Primary_exchange,
c.Company.Sector_code,
c.Sector.Description
});
I want to add the following SQL command to the above LINQ query and still maintain the projections:
SELECT
sector_code, industry_code
FROM
distribution_sector_industry
WHERE
service = 'numerical'
The 3rd join would be made with Sector table & Distribution_sector_industry on sector_code.
Thanks in advance.
Just a guess:
var myList = Companies
.Join(
Sectors,
comp => comp.Sector_code,
sect => sect.Sector_code,
(comp, sect) => new { Company = comp, Sector = sect })
.Join(
DistributionSectorIndustry.Where(dsi => dsi.Service == "numerical"),
cs => cs.Sector.Sector_code,
dsi => dsi.Sector_code,
(cs, dsi) => new { cs.Company, cs.Sector, IndustryCode = dsi.Industry_code })
.Select(c => new {
c.Company.Equity_cusip,
c.Company.Company_name,
c.Company.Primary_exchange,
c.Company.Sector_code,
c.Sector.Description,
c.IndustryCode
});
Okay, I can't see why you'd want to select sector_code when you already know it, but I think you want this:
var query = from company in Companies
join sector in Sectors
on company.SectorCode equals sector.SectorCode
join industry in DistributionSectorIndustry
on sector.SectorCode equals industry.SectorCode
where industry.Service == "numerical"
select new {
company.EquityCusip,
company.CompanyName,
company.PrimaryExchange,
company.SectorCode,
sector.Description,
industry.IndustryCode
};
Notes:
I've changed it into a query expression as that's a much more readable way of expressing a query like this.
Although the "where" clause comes after the join, assuming this is a LINQ to SQL or Entity Framework query, it shouldn't make any difference
I've lengthened the range variable names for clarity
I've converted your other names into conventional .NET names; you can do this too in your model
For 4 Tables
var query = CurrencyDeposits
.Join(Customers, cd => cd.CustomerId, cus => cus.Id, (cd, cus)
=> new { CurrencyDeposit = cd, Customer = cus })
.Join(Currencies, x => x.CurrencyDeposit.CurrencyId, cr => cr.Id, (x, cr)
=> new { x.CurrencyDeposit, x.Customer, Currency = cr })
.Join(Banks, x => x.CurrencyDeposit.BankId, bn => bn.Id, (x, bn)
=> new { x.CurrencyDeposit, x.Customer, x.Currency, Bank = bn})
.Select(s => new {
s.CurrencyDeposit.Id,
s.Customer.NameSurname,
s.Currency.Code,
s.Bank.BankName,
s.CurrencyDeposit.RequesCode
});
Try something like this...
var myList = ({from a in Companies
join b in Sectors on a.Sector_code equals b.Sector_code
join c in Distribution on b.distribution_code equals a.distribution_code
select new {...});
I would like to "combine" to linq queries into the same gridview. Though I don't think I could use innerjoin on this.
The queries get orders from the database, and I have 2 tables with orders from different places.
In the gridview I want to display all orders from first table and second table.
Like this:
OrderID - Item - Amount etc ---From table 1
OrderID - Item - Amount etc ---From table 2
etc..
My current query for getting orders from the first table are:
var query = from o in db.Orders
join y in db.OrderLines on o.OrderID equals y.OrderID
join x in db.Products on y.ItemNumber equals x.ItemNumber
where o.AccountNumber == AppSession.CurrentLoginTicket.AccountNumber
select new
{
o.OrderID,
o.AxaptaSalesId,
y.ItemNumber,
x.Name,
x.ProductFormatName,
y.Quantity,
y.Price,
Status = dltRep.getOrderStatus(o.OrderID, o.AxaptaSalesId, y.ItemNumber).Substring(0, dltRep.getOrderStatus(o.OrderID, o.AxaptaSalesId, y.ItemNumber).LastIndexOf("|")),
Levering = dltRep.getOrderStatus(o.OrderID, o.AxaptaSalesId, y.ItemNumber).Substring(dltRep.getOrderStatus(o.OrderID, o.AxaptaSalesId, y.ItemNumber).LastIndexOf("|")).Replace("|", "")
};
The other table would have the same information. It's named AxSale.
I hope this is possible and someone could help me out :)
EDIT: new "problem"
I wan't to get the variable createdDate to be the first element x.CreatedDate in either the first linq seq. or the second.
How do I do this?
var created = purchases.OrderByDescending(x => x.CreatedDate).
Select(x => new { x.CreatedDate, x.LineSupplierAccountNO }).
GroupBy(x => x.LineSupplierAccountNO);
if (created.Count() > 1)
{
created = purchases.OrderBy(x => x.CreatedDate).
Select(x => new { x.CreatedDate, x.LineSupplierAccountNO }).
GroupBy(x => x.LineSupplierAccountNO);
}
var createdDate = created.FirstOrDefault();
Solution code:
var created = purchases.OrderBy(x => x.CreatedDate).Select(x => x);
if (created.GroupBy(x => x.LineSupplierAccountNO).Count() > 1)
{
created = purchases.OrderByDescending(x => x.CreatedDate).Select(x => x);
}
var createdDate = created.First().CreatedDate;
Use UNION operator to join results with same fields. Here is example from http://code.msdn.microsoft.com/windowsdesktop/101-LINQ-Samples-3fb9811b
public void Linq49()
{
List<Product> products = GetProductList();
List<Customer> customers = GetCustomerList();
var productFirstChars =
from p in products
select p.ProductName[0];
var customerFirstChars =
from c in customers
select c.CompanyName[0];
var uniqueFirstChars = productFirstChars.Union(customerFirstChars);
Console.WriteLine("Unique first letters from Product names and Customer names:");
foreach (var ch in uniqueFirstChars)
{
Console.WriteLine(ch);
}
}
I believe you are looking for Union
Try this link
I am looking for a solution to have all the content of the table PART (by adding a right/left join I suppose) in the following LINQ query :
var query = (from p in db.PARTS
join oc in db.OUTPUT_CONTROLS on p.id equals oc.partid
join f in db.FCT on p.fct equals f.id
select new
{ p.id, p.plant, p.unit, p.type, p.num, f.name, oc.datetime, oc.ncr }
into x
group x by new
{ x.id, x.plant, x.unit, x.type, x.num, x.name }
into g
select new
{ g.Key.id, g.Key.plant, g.Key.unit, g.Key.type, g.Key.num, g.Key.name, startdate = g.Min(oc => oc.datetime), endate = g.Max(oc => oc.datetime), sumncr = g.Sum(oc => oc.ncr) })
.OrderByDescending(oc => oc.startdate);
Thanks
I found the solution on my own thanks to this post : LINQ Left Join And Right Join
The solution :
var query = (from p in db.PARTS
join oc in db.OUTPUT_CONTROLS on p.id equals oc.partid into joined
join f in db.FCT on p.fct equals f.id
from j in joined.DefaultIfEmpty()
select new
{ p.id, p.plant, p.unit, p.type, p.num, f.name, j.datetime, j.ncr } into x
group x by new { x.id, x.plant, x.unit, x.type, x.num, x.name } into g
select new { g.Key.id, g.Key.plant, g.Key.unit, g.Key.type, g.Key.num, g.Key.name, startdate = g.Min(oc => oc.datetime), endate = g.Max(oc => oc.datetime), sumncr = g.Sum(oc => oc.ncr) })
.OrderByDescending(oc => oc.startdate);
If you have a SQL where you see a join followed by a GroupJoin, consider using the LINQ GroupJoin.
Quite often you'll see this in situations where you want "Schools with their Students", "Customers with their Orders", "Zoos with their Animals"
It seems that you have 3 tables: Parts, OutputControls and Fcts.
Every Part has zero or more OutputControls, and every OutputControl belongs to exactly one Part, using foreign key PartId: a straightforward one-to-many relation
A Part has a foreign key FctId, that points to the Fct of the part.
You want (some properties of) the Parts, with their OutputControls and its Fct
var result = parts.GroupJoin(outputControls, // GroupJoin Parts and OutputControls
part => part.Id, // from every part take the Id
outputControl => outputControl.PartId, // from every outputControl take the PartId
// result selector: when these Ids match,
// use the part and all its matching outputControls to make one new object:
(part, outputControlsOfThisPart) => new
{
// select the part properties you plan to use:
Id = part.id,
Plant = part.plant,
Unit = part.unit
// the output controls of this part:
OutputControls = outputControlsOfThisPart.Select(outputControl => new
{
// again, select only the output control properties you plan to use
Id = outputControl.Id,
Name = outputControl.Name,
...
})
.ToList(),
// For the Fct, take the Fct with Id equal to Part.FctId
Fct = Fcts.Where(fct => fct.Id == part.Fct)
.Select(fct => new
{
// select only the Fct properties you plan to use
Id = fct.Id,
Name = fct.Name,
...
})
// expect only one such Fct
.FirstOrDefault(),
});