I have seen several answers to this query, but none have worked for me.
We have multiple mySql tables:
shipments
customers
suppliers
rebillingaudits
in my query I want to pull up the shipments with their customer and supplier and the most recent rebillingaudit record. This is what I have:
var results = context.Shipments.AsNoTracking().Where(x => customerIds.Contains(x.CustomerId.Value) && x.ProcessStageFlag == "REBILL_AUDIT")
.Join(context.Customers.AsNoTracking(),
im => im.CustomerId,
cu => cu.CustomerId,
(im, cu) => new { Shipments = im, Customers = cu }).DefaultIfEmpty()
.Join(context.Suppliers.AsNoTracking(),
im => im.Shipments.SupplierId,
su => su.SupplierId,
(im, su) => new { Shipments = im.Shipments, Customers = im.Customers, Suppliers = su }).DefaultIfEmpty()
.GroupJoin(context.RebillingAudit.AsNoTracking().OrderByDescending(x => x.LastUpdatedOn), //.Take(1),
im => new {im.Shipments.TrackingNumber, im.Shipments.CarrierInvoiceNumber},
rn => new {rn.TrackingNumber, CarrierInvoiceNumber = rn.InvoiceNumber},
(im, rn) => new { MatchingAssignments = im.MatchingAssignments, Shipments = im.Shipments, Suppliers = im.Suppliers, MatchResolutions = im.MatchResolutions, Customers = im.Customers, RebillingAudit = rn })
.SelectMany(
x => x.RebillingAudit.DefaultIfEmpty(),
(x, y) => new { MatchingAssignments = x.MatchingAssignments, Shipments = x.Shipments, Suppliers = x.Suppliers, MatchingResolutions = x.MatchResolutions, Customers = x.Customers, RebillingAudit = y })
.Where(x => x.MatchingAssignments.IsRebill &&
x.MatchingAssignments.IsActive)
.Select(m => new CustomerRebills()
{
TrackingNumber = m.Shipments.TrackingNumber,
Customer = m.Customers.InternalCustomerName,
CarrierInvoice = m.Shipments.CarrierInvoiceNumber,
RebillNotes = m.RebillingAudit == null ? "" : m.RebillingAudit.Notes
}).ToList();
This is the SQL query that I am attempting to replicate:
FROM invoice_master im
JOIN customer c ON im.VPL_customer_ID = c.Customer_ID
JOIN supplier s ON im.Supplier_ID = s.Supplier_ID
LEFT OUTER JOIN rebilling_audit rn ON im.Tracking_Number = rn.tracking_number AND im.Invoice_Number = rn.Invoice_number AND rn.last_updated_on =
(SELECT MAX(last_updated_on) FROM rebilling_audit WHERE tracking_number = im.tracking_number AND Invoice_number = im.invoice_number)
I have tried adding .Take(1) and I do not get what I expect.
I have tried .FirstOrDefault() and I get an error.
Thanks,
Sammer
Using my SQL to LINQ Recipe, translating the SQL more or less directly, I get
var results = (from im in context.InvoiceMaster
join c in context.Customers on im.CustomerId equals c.CustomerId
join s in context.Suppliers on im.Shipments.SupplierId equals s.SupplierId
join rn in context.RebillingAudit on new { im.Shipments.TrackingNumber, im.Shipments.CarrierInvoiceNumber } equals new { rn.TrackingNumber, CarrierInvoiceNumber = rn.InvoiceNumber } into rnj
from rn in rnj.Where(rn => rn.LastUpdatedOn == context.RebillingAudit.Where(ra => ra.TrackingNumber == im.Shipments.TrackingNumber && rn.InvoiceNumber == im.Shipments.CarrierInvoiceNumber).Max(rn => rn.LastUpdatedOn)).DefaultIfEmpty()
select new CustomerRebills() {
TrackingNumber = im.Shipments.TrackingNumber,
Customer = c.InternalCustomerName,
CarrierInvoice = im.Shipments.CarrierInvoiceNumber,
RebillNotes = rn == null ? "" : rn.Notes
}).ToList();
This is what I did to get the latest record:
var results = context.Shipments.AsNoTracking().Where(x => customerIds.Contains(x.CustomerId.Value) && x.ProcessStageFlag == "REBILL_AUDIT")
.Join(context.Customers.AsNoTracking(),
im => im.CustomerId,
cu => cu.CustomerId,
(im, cu) => new { Shipments = im, Customers = cu }).DefaultIfEmpty()
.Join(context.Suppliers.AsNoTracking(),
im => im.Shipments.SupplierId,
su => su.SupplierId,
(im, su) => new { Shipments = im.Shipments, Customers = im.Customers, Suppliers = su }).DefaultIfEmpty()
.GroupJoin(context.RebillingAudit.AsNoTracking().OrderByDescending(x => x.LastUpdatedOn), //.Take(1),
im => new {im.Shipments.TrackingNumber, im.Shipments.CarrierInvoiceNumber},
rn => new {rn.TrackingNumber, CarrierInvoiceNumber = rn.InvoiceNumber},
(im, rn) => new { MatchingAssignments = im.MatchingAssignments, Shipments = im.Shipments, Suppliers = im.Suppliers, MatchResolutions = im.MatchResolutions, Customers = im.Customers, RebillingAudit = rn })
.SelectMany(
x => x.RebillingAudit.DefaultIfEmpty(),
(x, y) => new { MatchingAssignments = x.MatchingAssignments, Shipments = x.Shipments, Suppliers = x.Suppliers, MatchingResolutions = x.MatchResolutions, Customers = x.Customers, RebillingAudit = y })
.Where(x => x.MatchingAssignments.IsRebill &&
x.MatchingAssignments.IsActive)
.Select(m => new CustomerRebills()
{
TrackingNumber = m.Shipments.TrackingNumber,
Customer = m.Customers.InternalCustomerName,
CarrierInvoice = m.Shipments.CarrierInvoiceNumber,
RebillNotes = m.RebillingAudit == null ? "" : m.RebillingAudit.Notes
}).ToList().OrderByDescending(x => x.RebillNotesWhen).GroupBy(y => new {y.TrackingNumber, y.CarrierInvoice, y.BillToAccount, y.CustomerId}).Select(z => z.FirstOrDefault()).ToList();
All my changes are in the last line.
I added an OrderByDescending to get the most recent record to the top, I added a GroupBy to collect each individual role, then I only take the first with the FirstOrDefault.
This resulted in me getting one record per TrackingNumber, CarrierInvoice, BillToAccount, and CustomerId and making sure that the one record was the latest.
I hope this helps someone.
Sammer
I'm trying to convert the SQL below to Linq. I haven't figured out the syntax for the GROUP BY, the MIN() or the extra organization join conditions.
SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr, MIN(a.SystemCreatedOnDtm) MinCreated
FROM vw_DimLabAsset a
INNER JOIN vw_FactWorker w ON a.LabAssetAssignedToWorkerKey = w.WorkerKey
INNER JOIN vw_DimOrganizationHierarchy o ON w.OrganizationHierarchyKey = o.OrganizationHierarchyKey
AND o.OrganizationHierarchyUnitLevelThreeNm IS NOT NULL
AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
This is what I've managed to get so far:
var pphw = from a in Vw_DimLabAsset
where a.LabAssetHardwareStatus != "Retired" && (a.LabAssetHardwareSubStatus == null || a.LabAssetHardwareSubStatus != "Archive") && types.Contains(a.LabAssetTypeNm) // (a.LabAssetTypeNm == "u_cmdb_ci_prototype_system" || a.LabAssetTypeNm == "u_cmdb_ci_silicon")
join w in Vw_FactWorker on a.LabAssetAssignedToWorkerKey equals w.WorkerKey
join o in Vw_DimOrganizationHierarchy on w.OrganizationHierarchyKey equals o.OrganizationHierarchyKey
select new { o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr };
Here is how I would translate the query:
var ans = (from a in vw_DimLabAsset
join w in vw_FactWorker on a.LabAssetAssignedToWorkerKey equals w.WorkerKey
join o in vw_DimOrganizationHierarchy on w.OrganizationHierarchyKey equals o.OrganizationHierarchyKey
where o.OrganizationHierarchyUnitLevelThreeNm != null && o.OrganizationHierarchyUnitLevelFourNm != null
group new { o, a } by new { o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr } into oag
select new {
oag.Key.OrganizationHierarchyUnitLevelThreeNm,
oag.Key.OrganizationHierarchyUnitLevelFourNm,
oag.Key.LabAssetSerialNbr,
MinCreated = oag.Min(oa => oa.a.SystemCreatedOnDtm)
}).Distinct();
I am using JPA2/Hibernate5 with Java8 over MySql.
I run the following native query:
Query q = entityManager.createNativeQuery(sb.toString(), JobWithDistance.class);
q.setParameter("ids", ids);
List<JobWithDistance> jobsWD = (List<JobWithDistance>) q.getResultList();
The sql in sb returns 3 rows when I run it directly against the database with the same parameters. However, when I run the native query via Hibernate, I only get one row.
Why are the results different?
More info:
Hibernate returns 1 row:
StringBuilder sb = getFindQuery();
sb.append(" where e.id in (:ids) ");
Query q = entityManager.createNativeQuery(sb.toString(), JobWithDistance.class);
q.setParameter("ids", ids);
//Object o = q.getResultList();
List<JobWithDistance> jobsWD = q.getResultList();
and
private StringBuilder getFindQuery() {
StringBuilder sb = new StringBuilder();
sb.append(" select * ");
sb.append(" , -1 as noReviews, -1 as averageRating ");
sb.append(" , -1 AS distance ");
sb.append(" from ");
sb.append(" www.job as e ");
sb.append(" inner join www.person_job as pj on e.id = pj.JOB_ID ");
sb.append(" inner join www.person as p on pj.PER_ID = p.id ");
sb.append(" left join www.rating_job rp ON e.id = rp.JOB_ID ");
sb.append(" left join www.rating r ON rp.RAT_ID = r.id ");
return sb;
}
The following SQl when run against the database, returns 3 rows:
select * , -1 as noReviews, -1 as averageRating , -1 AS distance from www.job as e inner join www.person_job as pj on e.id = pj.JOB_ID inner join www.person as p on pj.PER_ID = p.id left join www.rating_job rp ON e.id = rp.JOB_ID left join www.rating r ON rp.RAT_ID = r.id where e.id in (65, 66, 64)
Thanks
SOLUTION:
#Override
public List<Job> findById(String ids) {
String[] args = ids.split(",");
Set<String> idSet = new HashSet<String>(Arrays.asList(args));
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Job> query = builder.createQuery(Job.class);
Root<Job> post = query.from(Job.class);
query.select(post).where(post.get("id").in(idSet)); // or pass a tag collection to `in` method
TypedQuery<Job> typedQuery = entityManager.createQuery(query);
List<Job> results = typedQuery.getResultList();
return results;
}
what's the linq lambda expression for the following mysql query
Select Count(*), Users.BusinessName From Offers
inner join Users on Users.UserId = Offers.UserId
inner join RoleUsers on RoleUsers.User_UserId = Users.UserId
inner join Roles on Roles.RoleId = RoleUsers.Role_RoleId
where Roles.RoleName = 'Seller'
group by Users.BusinessName
Counts the Number of Offers and Groups it by the User's Name ( where the User is a seller).
public static List<CountsByUser> NoOffersByUserType()
{
List<Offer> offers;
using (MainDb ctx = new MainDb())
{
var role = ctx.Roles.FirstOrDefault(r => r.RoleName == "Seller");
List<User> users = role.Users.ToList();
offers= ctx.OfertaPret.Any(u => u.User == users).ToList();
//here is the problem u.User ==users
}
List<CountsByUser> requests = offers.GroupBy(o => o.User.BusinessName)
.Select(nl => new CountsByUser
{
name = nl.Key,
number = nl.Count()
})
.ToList();
return requests;
}
offers= ctx.OfertaPret.Include(u=>u.User)
.Where(u => u.User.Roles.Any(r => r.RoleName == "Seller")).ToList();
I have a Sql table tblEMP (EmpID,FirstName, LastName, BranchID, DOB).
Now I want to get matches Emp details as following condition:
Here F = FirstName, L= LastName, B = BranchID, D = DOB
1) Matching :
F == F And
L == L And
B == B And
D == D
2) Probable :
F == F And
L == L And
(S == S or D == D )
3) Possible :
F != F And
L == L And
(S == S or D == D )
I have Added a filed MatchType and set its value as per Emp detail match.
I have completed this using Dataset comparison but it take more time to compare data.
I have used below code and in dsNameMerge I have all EmpDetail:
for (int i = 0; i < dsNameMerge.Tables[0].Rows.Count; i++)
{
if (i == dsNameMerge.Tables[0].Rows.Count - 1)
break;
DataRow dr = dsNameMerge.Tables[0].Rows[i];
DataRow dr1 = dsNameMerge.Tables[0].Rows[i + 1];
... Compare as per above condition and set MatchType and create a Dataset table and insert matched emp detail with MatchType in it.
}
Now I want to do this task using Stored procedure.
How can I do this thing in Stored procedure?
Thanks