LINQ - Left Outer Join with multiple parameters in Where clause - sql

How can I do this SQL query in LINQ:
select * from chat c
left outer join lead s on c.key = s.id
where (typeId = 5 AND c.key = #clientId) OR (c.typeId = 4 AND s.clientId = #clientId)
Or this SQL query -- Same, same
select * from chat c
where (typeId = 5 AND c.key = #clientId) OR (typeId = 4 AND c.key in (select id from lead where clientId = #clientId))
What I have:
var chatter = (from chat in linq.Chat
join lead in linq.Lead
on chat.key equals lead.Id.ToString() into clientLeads
from cl in clientLeads.Where(l => l.clientId == clientId).DefaultIfEmpty()
where (chat.typeId == 5 && chat.key == clientId.ToString()) ||
(chat.typeId == 4 && chat.key == cl.Id.ToString())
select chat).WithPath(prefetchPath).OrderByDescending(c => c.CreatedDate);
The above LINQ query doesn't yeild any results from the latter WHERE clause, what am I missing?

I translated the second query to linq:
var leadIds = linq.Lead.Where(l => l.clientId == clientId.ToString()).Select(l => l.id);
var chatter = from chat in linq.Chat
where (chat.typeId == 5 && chat.key == clientId.ToString()) ||
(chat.typeId == 4 && leadIds.Contains(chat.key));

Related

Database query - unusual query

I'm trying to transfer a query to LINQ
It's a bit complicated and I don't know if I'm doing the right thing
There is also a problem with SELECT to save it properly
SQL QUERY:
SELECT ISNULL(SUM(1),0) TotalSubmitted,
ISNULL(SUM(CASE WHEN Pic.PhotoFileName IS NULL THEN 0 ELSE 1 END),0) TotalAssigned
FROM tblFromPhone Ph
INNER JOIN tblOfficer O ON Ph.OfficerCode = O.Code
OUTER APPLY(SELECT PhotoFileName FROM tblPhotos P
WHERE P.validityTo IS NULL
AND P.PhotoFileName = Ph.DocName
AND P.OfficerID = O.OfficerID)Pic
WHERE CAST(Ph.LandedDate AS DATE) BETWEEN #FromDate AND #ToDate
AND O.ValidityTo IS NULL
AND DocType = N'E'
AND OfficerCode = #OfficerCode
My LINQ:
var res = (from FP in context.TblFromPhone
join O in context.TblOfficer on FP.OfficerCode equals O.Code
join P in context.TblPhotos on FP.DocName equals P.PhotoFileName into P
from Ph in P.Where(x => x.OfficerId == O.OfficerId).DefaultIfEmpty()
where Ph.ValidityTo == null
where FP.LandedDate >= DateTime.Parse(fromDate)
&& FP.LandedDate <= DateTime.Parse(toDate)
&& O.ValidityTo == null
&& FP.DocType == "E"
&& FP.OfficerCode == officerCode
select new EnrolmentModel()
{
TotalSubmitted = // How to make?
TotalAssigned = // How to make?
})
.FirstOrDefault();

Linq To entity no full join issue

I have the following SQL script that gives me the results i'm after , i'm having trouble replicating the full join and the count distinct on the activities count:
select ActivityCount,ActivityComplete, ImagePath, SubjectTitle from
(select
Count(Distinct(Act.[ActivityID])) as ActivityCount,
Sum(Case when (([OutcomeID] = 1 or [OutcomeID] = 3) and AOU.ActivityUserID=1 ) Then 1 Else 0 End) As ActivityComplete,
Sub.[SubjectImageName] as ImagePath,
Sub.SubjectTitle as SubjectTitle
from [dbo].[UserActivityOutcome] AOU
full join Activity Act on Act.[ActivityID] = AOU.[ActivityID]
left join Category Cat on Act.[CategoryID] = Cat.[CategoryID]
left join Subject Sub on Cat.[SubjectID] = Sub.[SubjectID]
group by Sub.SubjectTitle, Sub.[SubjectImageName]
) as x
results:
</head>
<body><div class="spacer"><table id="t1"><tr><td class="typeheader" colspan="4">Result Set (2 items)</td></tr><tr><th title="System.Int32">ActivityCount</th><th title="System.Int32">ActivityComplete</th><th title="System.String">ImagePath</th><th title="System.String">SubjectTitle</th></tr><tr><td class="n">25</td><td class="n">3</td><td>Subject 1.png</td><td>Subject 1</td></tr><tr><td class="n">1</td><td class="n">1</td><td>Subject 2.png</td><td>Subject 2</td></tr><tr><td title="Total=26
Average=13" class="columntotal">26</td><td title="Total=4
Average=2" class="columntotal">4</td><td title="Totals" class="columntotal"></td><td title="Totals" class="columntotal"></td></tr></table></div></body>
</html>
my linq looks like this:
from x in (
(from Act in Activities
join AOU in UserActivityOutcomes on Act.ActivityID equals AOU.ActivityID into AOU_join
from AOU in AOU_join.DefaultIfEmpty()
join ActNA in Activities on AOU.ActivityID equals ActNA.ActivityID into ActNA_join
from ActNA in ActNA_join.DefaultIfEmpty()
join Cat in Categories on AOU.Activity.CategoryID equals Cat.CategoryID into Cat_join
from Cat in Cat_join.DefaultIfEmpty()
join Sub in Subjects on Cat.SubjectID equals Sub.SubjectID into Sub_join
from Sub in Sub_join.DefaultIfEmpty()
group new {Sub, AOU, Act,ActNA} by new {
Sub.SubjectTitle,
Sub.SubjectImageName
} into g
select new {
ActivityCount = g.Distinct().Count(), //g.Count(),
ActivityComplete = g.Sum(p => (
(p.AOU.OutcomeID == 1 ||
p.AOU.OutcomeID == 3)&&
p.AOU.ActivityUserID == 23 ? 1 : 0)),
ImagePath = g.Key.SubjectImageName,
SubjectTitle = g.Key.SubjectTitle
}))
select new {
x.ActivityCount,
x.ActivityComplete,
x.ImagePath,
x.SubjectTitle
}
LINQ full outer join is tricky. The only way it could be simulated is by union of left outer join and right antijoin. Here is IMO the LINQ equivalent of your SQL query:
var query =
// AOU full join Act
(from e in (from AOU in UserActivityOutcomes
join Act in Activities on AOU.ActivityID equals Act.ActivityID into Act_join
from Act in Act_join.DefaultIfEmpty()
select new { AOU, Act })
.Concat
(from Act in Activities
join AOU in UserActivityOutcomes on Act.ActivityID equals AOU.ActivityID into AOU_join
from AOU in AOU_join.DefaultIfEmpty()
where AOU == null
select new { AOU, Act })
let AOU = e.AOU
let Act = e.Act
// left join Cat
join Cat in Categories on Act.CategoryID equals Cat.CategoryID into Cat_join
from Cat in Cat_join.DefaultIfEmpty()
// left join Sub
join Sub in Subjects on Cat.SubjectID equals Sub.SubjectID into Sub_join
from Sub in Sub_join.DefaultIfEmpty()
group new { Sub, AOU, Act } by new { Sub.SubjectTitle, Sub.SubjectImageName } into g
select new
{
ActivityCount = g.Where(e => e.Act != null).Select(e => e.Act.ActivityID).Distinct().Count(),
ActivityComplete = g.Sum(e => (e.AOU.OutcomeID == 1 || e.AOU.OutcomeID == 3) && e.AOU.ActivityUserID == 1 ? 1 : 0),
ImagePath = g.Key.SubjectImageName,
SubjectTitle = g.Key.SubjectTitle
};

Massive SQL query requires conversion to LINQ

I have an SQL query which I need to convert to LINQ. have spent a whole day on it, didn't have much luck tough. Here's the query
SELECT PC.PRSCLAIMID,
date_format(PC.DATEOFCLAIM, '%d/%m/%Y') as DateofClaim,
PC.PRSREFNO,
PC.FKARTISTID,
PC.FKSETLISTINFOID,
PC.STATUS,
PC.FROMDNN,
PC.EXPORTTYPE,
PC.FK_CATEGORYID,
A.LOGINNAME,
A.BANDNAME,
SMCATEGORIESTYPE.CATEGORYTYPE,
Count(SMLIVECLAIMS.LIVECLAIMSID) AS GIGCOUNT,
SMCATEGORIES.ID AS PROCESSEDID,
SMCATEGORIES.CATEGORY,
Ifnull(BC.FILENAME, '') AS BULKCLAIM_NAME
FROM SMARTISTDETAILS AS A
INNER JOIN SMPRSCLAIMS AS PC
ON A.ARTISTID = PC.FKARTISTID
INNER JOIN SMCATEGORIES
ON PC.FK_CATEGORYID = SMCATEGORIES.ID
INNER JOIN SMCATEGORIESTYPE
ON SMCATEGORIES.FK_CATEGORYTYPEID = SMCATEGORIESTYPE.ID
INNER JOIN SMPRSLIVECLAIMLINK
ON PC.PRSCLAIMID = SMPRSLIVECLAIMLINK.FKPRSCLAIMID
INNER JOIN SMLIVECLAIMS
ON SMPRSLIVECLAIMLINK.FKLIVECLAIMID = SMLIVECLAIMS.LIVECLAIMSID
LEFT OUTER JOIN BULKCLAIMDETAIL BCD
ON BCD.FKPRSCLAIMID = PC.PRSCLAIMID
LEFT OUTER JOIN BULKCLAIM BC
ON BC.ID_BULKCLAIM = BCD.ID_BULKCLAIM
WHERE ( PC.EXPORTTYPE > 0 )
AND ( A.DBID = 1 )
AND ( CASE
WHEN PC.EXPORTTYPE = 1
AND ( SMLIVECLAIMS.GIGDATE < Date_add(Now(), INTERVAL -1 YEAR) ) THEN 0
ELSE 1
END = 1 )
GROUP BY PC.PRSCLAIMID
ORDER BY PC.DATEOFCLAIM DESC
what I did was the following conversion
from e in
(from artistData in dbContext.smartistdetails where artistData.DbId == 1 // SessionFacade.DBId
join smprsclaimsData in dbContext.smprsclaims on artistData.ArtistID equals smprsclaimsData.fkArtistID join smCategoriesData in dbContext.smcategories on smprsclaimsData.FK_CategoryID equals smCategoriesData.Id join smCategoriesTypeData in dbContext.smcategoriestype on smCategoriesData.fk_CategoryTypeId equals smCategoriesTypeData.Id join smPrsLiveClaimsLinkData in dbContext.smprsliveclaimlink on smprsclaimsData.PRSClaimID equals smPrsLiveClaimsLinkData.fkPRSClaimID join smLiveClaimData in dbContext.smliveclaims on smPrsLiveClaimsLinkData.fkLiveClaimID equals smLiveClaimData.LiveclaimsID join bulkClaimDetailData in dbContext.bulkclaimdetail on smprsclaimsData.PRSClaimID equals bulkClaimDetailData.fkPRSClaimID into bulkClaimDetailJoined from bulkClaimDetailJoinedData in bulkClaimDetailJoined.DefaultIfEmpty() join bulkClaimData in dbContext.bulkclaim on bulkClaimDetailJoinedData.ID_BulkClaim equals bulkClaimData.ID_BulkClaim into bulkClaimJoined from bulkClaimJoinedData in bulkClaimJoined.DefaultIfEmpty() where smprsclaimsData.ExportType > 0 select new {
PRSCLAIMID_Inner = smprsclaimsData.PRSClaimID,
GigDate = smLiveClaimData.GigDate,
DateofClaim = smprsclaimsData.DateofClaim,
PRSREFNO = smprsclaimsData.PRSRefNo,
FKARTISTID = smprsclaimsData.fkArtistID,
FKSETLISTINFOID = smprsclaimsData.fkSetlistInfoID,
STATUS = smprsclaimsData.Status,
FROMDNN = smprsclaimsData.FromDNN,
EXPORTTYPE = smprsclaimsData.ExportType,
FK_CATEGORYID = smprsclaimsData.FK_CategoryID,
LOGINNAME = artistData.LoginName,
BANDNAME = artistData.BandName,
CATEGORYTYPE = smCategoriesTypeData.CategoryType,
LiveclaimsID = smLiveClaimData.LiveclaimsID,
PROCESSEDID = smCategoriesData.Id,
CATEGORY = smCategoriesData.Category,
BULKCLAIM_NAME = bulkClaimJoinedData.FileName == null ? "" : bulkClaimJoinedData.FileName
})
where!(e.EXPORTTYPE == 1 && e.GigDate < oneYearOldDate)
group e by e.PRSCLAIMID_Inner into groupedData
select new {
PRSCLAIMID_Outer = groupedData.Key,
GIGCOUNT = groupedData.Count(),
DateofClaim = groupedData.Select(a = > a.DateofClaim).FirstOrDefault(),
PRSREFNO = groupedData.Select(a = > a.PRSREFNO).FirstOrDefault(),
FKARTISTID = groupedData.Select(a = > a.FKARTISTID).FirstOrDefault(),
FKSETLISTINFOID = groupedData.Select(a = > a.FKSETLISTINFOID).FirstOrDefault(),
STATUS = groupedData.Select(a = > a.STATUS).FirstOrDefault(),
FROMDNN = groupedData.Select(a = > a.FROMDNN).FirstOrDefault(),
EXPORTTYPE = groupedData.Select(a = > a.EXPORTTYPE).FirstOrDefault(),
FK_CATEGORYID = groupedData.Select(a = > a.FK_CATEGORYID).FirstOrDefault(),
LOGINNAME = groupedData.Select(a = > a.LOGINNAME).FirstOrDefault(),
BANDNAME = groupedData.Select(a = > a.BANDNAME).FirstOrDefault(),
CATEGORYTYPE = groupedData.Select(a = > a.CATEGORYTYPE).FirstOrDefault(),
PROCESSEDID = groupedData.Select(a = > a.PROCESSEDID).FirstOrDefault(),
CATEGORY = groupedData.Select(a = > a.CATEGORY).FirstOrDefault(),
BULKCLAIM_NAME = groupedData.Select(a = > a.BULKCLAIM_NAME).FirstOrDefault()
}).OrderByDescending(a = > a.DateofClaim)
this conversion is working but it is too slow, then I create another conversion
from smprsclaimsData in dbContext.smprsclaims
group smprsclaimsData by new { smprsclaimsData.PRSClaimID, smprsclaimsData.fkArtistID, smprsclaimsData.FK_CategoryID } into smprsclaimsGroupedData
join artistData in dbContext.smartistdetails on smprsclaimsGroupedData.Key.fkArtistID equals artistData.ArtistID
let loginName = artistData.LoginName
let bandName = artistData.BandName
join smCategoriesData in dbContext.smcategories on smprsclaimsGroupedData.Key.FK_CategoryID equals smCategoriesData.Id
join smCategoriesTypeData in dbContext.smcategoriestype on smCategoriesData.fk_CategoryTypeId equals smCategoriesTypeData.Id
join smPrsLiveClaimsLinkData in dbContext.smprsliveclaimlink on smprsclaimsGroupedData.Key.PRSClaimID equals smPrsLiveClaimsLinkData.fkPRSClaimID
join smLiveClaimData in dbContext.smliveclaims on smPrsLiveClaimsLinkData.fkLiveClaimID equals smLiveClaimData.LiveclaimsID
join bulkClaimDetailData in dbContext.bulkclaimdetail on smprsclaimsGroupedData.Key.PRSClaimID equals bulkClaimDetailData.fkPRSClaimID into bulkClaimDetailJoined
from bulkClaimDetailJoinedData in bulkClaimDetailJoined.DefaultIfEmpty()
join bulkClaimData in dbContext.bulkclaim on bulkClaimDetailJoinedData.ID_BulkClaim equals bulkClaimData.ID_BulkClaim into bulkClaimJoined
from bulkClaimJoinedData in bulkClaimJoined.DefaultIfEmpty()
where smprsclaimsGroupedData.Select(a => a.ExportType).FirstOrDefault() > 0 && artistData.DbId == 1
&& !(smprsclaimsGroupedData.Select(a => a.ExportType).FirstOrDefault() == 1 && smLiveClaimData.GigDate < oneYearOldDate)
select new
{
PRSCLAIMID_Inner = 1,
GigDate = smLiveClaimData.GigDate,
DateofClaim = smprsclaimsGroupedData.Select(a => a.DateofClaim),
PRSREFNO = smprsclaimsGroupedData.Select(a => a.PRSRefNo),
FKARTISTID = smprsclaimsGroupedData.Select(a => a.fkArtistID),
FKSETLISTINFOID = smprsclaimsGroupedData.Select(a => a.fkSetlistInfoID),
STATUS = smprsclaimsGroupedData.Select(a => a.Status),
FROMDNN = smprsclaimsGroupedData.Select(a => a.FromDNN),
EXPORTTYPE = smprsclaimsGroupedData.Select(a => a.ExportType),
FK_CATEGORYID = smprsclaimsGroupedData.Select(a => a.FK_CategoryID),
LOGINNAME = loginName,
BANDNAME = bandName,
CATEGORYTYPE = smCategoriesTypeData.CategoryType,
//GIGCOUNT = smprsclaimsGroupedData.Count(),
PROCESSEDID = smCategoriesData.Id,
CATEGORY = smCategoriesData.Category,
BULKCLAIM_NAME = bulkClaimJoinedData.FileName == null ? "" : bulkClaimJoinedData.FileName,
})
well this query is not fetching the expected data, i think it is due to multiple (group by)'s. I cannot post my DB Schema as well, the question is already too long to read. Any help or any suggestions on how to get around or work around this conversion.
I think you are over thinking the LINQ a little, try the following LINQ. The only thing I am not 100% sure about is the GIGCOUNT results so that might take a bit of fiddling with.
(
from A in SMARTISTDETAILS
join PC in SMPRSCLAIMS on A.ARTISTID equals PC.FKARTISTID
join categories in SMCATEGORIES on PC.FK_CATEGORYID equals categories.ID
join categoryType in SMCATEGORIESTYPE on categories.FK_CATEGORYTYPEID equals categoryType.ID
join link in SMPRSLIVECLAIMLINK on PC.PRSCLAIMID equals link.FKPRSCLAIMID
join liveClaims in SMLIVECLAIMS on link.FKLIVECLAIMID equals liveClaims.LIVECLAIMSID
join bulkDetail in BULKCLAIMDETAIL on PC.PRSCLAIMID equals bulkDetail.FKPRSCLAIMID into BULK_DETAILS
from BCD in BULK_DETAILS.DefaultIfEmpty()
join bulkClaim in BULKCLAIM on BCD.ID_BULKCLAIM equals bulkClaim.ID_BULKCLAIM into BULK_CLAIMS
from BC in BULK_CLAIMS.DefaultIfEmpty()
where
( PC.EXPORTTYPE > 0 )
&& ( A.DBID == 1 )
&& (
PC.EXPORTTYPE == 1 && liveClaims.GIGDATE < DateTime.Now.AddYears(-1) ? 0 : 1
) == 1
orderby PC.DATEOFCLAIM descending
select new
{
PC.PRSCLAIMID,
DateofClaim = PC.DATEOFCLAIM,
PC.PRSREFNO,
PC.FKARTISTID,
PC.FKLISTINFOID,
PC.STATUS,
PC.FROMDNN,
PC.EXPORTTYPE,
PC.FK_CATEGORYID,
A.LOGINNAME,
A.BANDNAME,
categoryType.CATEGORYTYPE,
// This gets me the correct count now
GIGCOUNT = SMPRSLIVECLAIMLINK.Where(LINK => LINK.FKPRSCLAIMID == PC.PRSCLAIMID && (PC.EXPORTTYPE == 1 && LINK.FKLIVECLAIMIDSMLIVECLAIMS.GIGDATE < DateTime.Now.AddYears(-1) ? 0 : 1) == 1).Count(),
PROCESSEDID = categories.ID,
categories.CATEGORY,
BULKCLAIM_NAME = BC.FILENAME ?? String.Empty
})
// Use distinct to get rid of duplicate rows
.Distinct()
.ToList()
.GroupBy(o =>
o.PRSCLAIMID
)
EDIT:
I changed how I calculate the GIGCOUNT property, this should now return the correct number. You will also want to use the Distinct() extension so that duplicate rows are removed.

INNER JOIN LEFT JOIN in LINQ to SQL

How to convert INNER JOIN and LEFT JOIN in the following SQL query to LINQ to SQL? Thanks!
SELECT transactions.postdate,
transactions.clientkey AS TransClientKey,
transactions.type AS TransType,
clients.clientno,
Isnull(clients.nostmt, 0) AS CliNoStmt,
Isnull(aging.nostmt, 0) AS AgeNoStmt,
pmtchecks.*
FROM ((pmtchecks
INNER JOIN transactions
ON pmtchecks.transkey = transactions.transkey)
INNER JOIN clients
ON transactions.clientkey = clients.clientkey)
LEFT JOIN aging
ON ( transactions.clientkey = aging.clientkey )
AND ( pmtchecks.debtorkey = aging.debtorkey )
WHERE ( pmtchecks.debtorkey = 36927 )
AND ( transactions.status = 0 )
AND ( transactions.postdate <= '31-May-2012' )
AND ( ( transactions.postdate >= '01-May-2012' )
OR ( clients.clientno = 'UNKNOWN' ) )
ORDER BY pmtchecks.checkdate,
pmtchecks.checkno
Hi this is kind of dummy code i cnt say its exactly right but the idea will be exactly same to get the result
var anonymousType= (from pm in pmtchecks
join tr in transactions
on pm.transkey equals tr.transkey //INNERJOIN
join cl in clients
on tr.clientKey equals cl.clientKey
join ag in aging
on pm.debtorkey equals ag.debtorKey into ljoin //Left Join
from lj in ljoin.DefaultOrEmpty()
where pm.debortkey==36927 && tr.status==0 && tr.postdate<="31-May-2012" && tr.postdate>="01-May-2012" //u will have to change this to date format first
Select new {PostDate=tr.postdate, TransClientKey=tr.clientkey,TransType=tr.type,ClientNo=cl.clientno,CliNoStmt=cl.nomst ?? 0,AgeNoStmt=ag.nomst ??0,Pmtchecks=pm } //Anonymous type from this you can extract the values and fill to your custom type
).OrderBy(o=>o.Pmtchecks.checkdate).OrderBy(o=>o.Pmtchecks.checkno).ToList();
Hope this will help.
LINQ Query Samples
EDITED
var pmtchecks = from p in urcontext.pmtchecks
join t in urcontext.transactions on p.transkey equals t.transkey
join a in urcontext.aging on t.clientkey equals a.clientkey into details
from d in details.Where( a => ( a.debtorkey == p.debtorkey)).DefaultIfEmpty()
where (p.debtorkey == 36927 && t.status == 0 && t.postdate <= '31-May-2012'
&& (t.postdate >= '01-May-2012' || c.clientno == 'UNKNOWN' ))
orderby p.checkdate, p.checkno
select new
{
t.postdate,
t.clientkey,
// TransClientKey = t.clientkey, //only works if TransClientKey is property
t.type ,
//TransTypet = t.type ,//property
c.clientno,
c.nostmt,
//CliNoStmt = c.nostmt ?? 0,//property
a.nostmt//,
//AgeNoStmt = nostmt ?? 0,//property
//p. ... //follow above for p columns
};

Linq 2 SQL Syntax Help

I am almost done converting a MySQL app to Linq2SQL but struggling to get my head round this last SQL query
SELECT a.URL, b.URL AS DuplicateURL
FROM Pages a
INNER JOIN Pages b ON a.MetaDescription = b.MetaDescription
AND a.PageID <> b.PageID
WHERE a.DomainID = #reportid
AND b.DomainID = #reportid
AND LENGTH(TRIM(a.MetaDescription)) > 0
AND a.URL < b.URL
ORDER BY a.URL ASC
Could anymore give me some syntax help on how I would create this query in Linq2SQL?
Any help greatly appreciated
It goes like this:
var DuplicatePages =
from a in DBContext.Pages
join b in DBContext.Pages on a.MetaDescription equals b.MetaDescription
where (a.PageID <> b.PageID) && (a.DomainID == ReportID) &&
(b.DomainID == ReportID) && (a.MetaDescription.Trim().Length > 0) &&
(a.URL < b.URL)
orderby a.URL
select new { Url = a.URL, DuplicateUrl = b.URL };
That's pretty straigtforward:
var reportId = ...;
var duplicates =
from a in db.Pages
from b in db.Pages
where a.MetaDescription == b.MetaDescription
where a.PageID != b.PageID
where a.DomainID == reportId
where b.DomainID == reportId
where a.MetaDescription.Trim().Length > 0
where a.URL < b.URL
orderby a.URL
select new { Url = a.URL, DuplicateUrl = b.Url }