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(),
});
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);
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),
};
I have tables similar like Employee, Manager, Branch, Division, Employee_history
And let us say two tables Employee and Manager share certain columns like employee_id, name, branch_id
Branch table has branch_id
Division table has division_id
Employee_history has emp_hist_id.
All of these tables are one-many relationships
The SQL I want to convert to LINQ is
select b.branch_id, e.employee_id
from division d
join branch b on d.division_id = b.division_id
join
( select employee_id, branch_id
from EMPLOYEE
UNION
select employee_id, branch_id
from MANAGER
) e
on e.branch_id = b.branch_id
join EMPLOYEE_HISTORY eh on eh.employee_id = e.employee_id
How do i do a UNION and then a join. I have put a simplified version of SQL than what I have. In my actual SQL, there are two or three joins before Branch table and one join after the union
And my LINQ looks like (similar to actual code)
from division in divisions
join brnch in Branch on division.division_id equals brnch.division_id
join empl in (
from emplyee in Employee select new { EmployeeId = emplyee.employee_id}, BrnachId = branch_id).Union(
from mngr in Manager select new { EmployeeId = mngr.employee_id, BrnachId = branch_id)
on brnch.branch_id equals empl.BranchId
join emplhistory in EMPLOYEE_HISTORY on empl.EmployeeId equals emplhistory.employee_id
where division.division_type_id = 10
select new
{
//...
}
I am getting the error:
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.
In the line that starts with 'join empl in ('
Your syntax for the on caluse of Join is slightly off. In C# it is not:
on division.division_id = brnch.division_id
it needs to be:
on division.division_id equals brnch.division_id
This needs to be changed for all of the on clauses.
In LINQ the order of the statements is a little bit reversed, as opposed to SQL. And when making a .Join() make sure the property names and types(!) are equal. You can't simply join an int on an int?, you have to cast the int to be int? also.
In the example below, I suppose the Branch_ID on Employee and Manager are nullable (int?).
DataContext.GetTable<Employee>()
.Select(e => new { e.ID, e.Name, e.Branch_ID })
.Union(DataContext.GetTable<Manager>()
.Select(m => new { m.ID, m.Name, m.Branch_ID }))
.Join(DataContext.GetTable<Branch>(),
u => new { Branch_ID = u.Branch_ID },
b => new { Branch_ID = (int?)b.ID },
(u, b) => new { u.ID, u.Name, u.Branch_ID, b.Branch_Name })
.Select(j => new { j.ID, j.Name, j.Branch_ID, j.Branch_Name });
And to finish it, I applied this to the actual code:
divisions
.Where(d => d.division_type_id == 10)
.Join(branches,
d => (int?)d.division_id,
b => b.division_id,
(d, b) => new { b.branch_id }) // j1
.Join(employees
.Select(e => new { e.employee_id, e.branch_id })
.Union(managers
.Select(m => new { m.employee_id, m.branch_id })),
j1 => (int?)j1.branch_id,
em => em.branch_id,
(j1, em) => new { em.employee_id, em.branch_id }) // j2
.Join(employeeHistory,
j2 => j2.employee_id,
h => h.employee_id,
(j2, h) => new { j2.employee_id, j2.branch_id, h.history_line }) // j3
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