convert sql subquery with multiple joins to linq - sql

I'm having trouble working in my subselect into LINQ. Here is the SQL followed by the LINQ. The SQL Query runs fine. The problem is incorporating the subquery. Any assistance would be appreciated:
SELECT DISTINCT
cic.CommitmentItemCategoryName + '( ' + cicType.CommitmentItemCategoryTypeName + ' )' AS displayCategory
, 'CategoryType_' + CAST(cic.CommitmentItemCategoryID AS VARCHAR(10)) AS displayCategoryID
, ISNULL(vwPAD.DollarsAllocated, 0) AS DisplayDollarsAllocated
,cic.CommitmentItemCategoryID
FROM
tblCommitmentItemCategory cic
LEFT OUTER JOIN
tblCommitmentItemCategoryType cicType ON cic.CommitmentItemCategoryTypeID = cicType.CommitmentItemCategoryTypeID
LEFT OUTER JOIN
tblAccountDirectToCommitmentItemCategory adToCIC ON adToCIC.CommitmentItemCategoryID IN (SELECT CommitmentItemCategoryID FROM tblCommitmentItemCategory)
LEFT OUTER JOIN
vw_ParentAccountDollarsAllocatedByCommitmentItemCategory vwPAD ON vwPAD.FiscalYear = 2015
AND cic.CommitmentItemCategoryID = vwPAD.CommitmentItemCategoryID
AND vwPAD.AccountDirectParentID = 19
WHERE
adToCIC.AccountDirectParentID = 19
ORDER BY
displayCategory
var queryInner = from cic in MyContext.tblCommitmentItemCategory
select new
{
cic.CommitmentItemCategoryID
};
var queryDollars = (from cic in MyContext.tblCommitmentItemCategory
join cicType in MyContext.tblCommitmentItemCategoryType
on cic.CommitmentItemCategoryTypeID equals cicType.CommitmentItemCategoryTypeID
into t2
from cicType in t2.DefaultIfEmpty()
join adToCIC in MyContext.tblAccountDirectToCommitmentItemCategory
//What goes here?
on ...
// on cic.CommitmentItemCategoryID equals adToCIC.CommitmentItemCategoryID
into t3
from adToCIC in t3.DefaultIfEmpty()
join vw in MyContext.vw_ParentAccountDollarsAllocatedByCommitmentItemCategory
on new { FiscalYear = currentFiscalYear, CommitmentItemCategory = cic.CommitmentItemCategoryID, ParentAccountID = currentParentAccountID }
equals new { FiscalYear = vw.FiscalYear, CommitmentItemCategory = vw.CommitmentItemCategoryID, ParentAccountID = vw.AccountDirectParentID }
into t
from vw in t.DefaultIfEmpty()
where adToCIC.AccountDirectParentID == currentParentAccountID
let displayCategory = cic.CommitmentItemCategoryName + " ( " + cicType.CommitmentItemCategoryTypeName + " )"
// Called CategoryType but it's actually the ID below
let displayCategoryTypeID = "CategoryType_" + cic.CommitmentItemCategoryID.ToString()
//let displayCategoryTypeID = "CategoryType!" + cic.CommitmentItemCategoryID + "_" + adToCIC.AccountDirectToCommitmentItemCategoryID.ToString()
let displayDollarsAllocated = vw.DollarsAllocated == null ? 0 : vw.DollarsAllocated
orderby cic.CommitmentItemCategoryName
select new
{
displayCategory,
displayCategoryTypeID,
cic.CommitmentItemCategoryID,
displayDollarsAllocated
}).Distinct();

Can you convert queryInner to a join? Then use that result in the larger query:
var queryInner =
from atcic in MyContext.tblAccountDirectToCommitmentItemCategory
join cic in MyContext.tblCommitmentItemCategory on atcic.CommitmentItemCategoryID equals cic.CommitmentItemCategoryID
select atcic;
And in the big query:
join adToCIC in queryInner into t3
from adToCIC in t3.DefaultIfEmpty()

Related

Change to linq left join query

SELECT I.*, SI.SupplierID FROM item I
LEFT JOIN SupplierItem SI ON I.ItemID = SI.ItemID AND I.Price = SI.Price
WHERE I.CurrentQty <= I.ReorderLevel and SI.SupplierID = 'AlPA'
how can i change that sql query to Linq Query.
The below query will convert your Sql query to Linq query
var data =
from row in db.item
join row1 in db.SupplierItem
on new { ID= row.ItemID , Price = row.Price }
equals new { ID= row1.ItemID , Price = row1.Price } into joinedData
from row2 in joinedData.DefaultIfEmpty()
where row.CurrentQty <= row.ReorderLevel && row2.SupplierID == "AlPA"
select new {
item = row,
SupplierID = row2.SupplierID
};

EclipseLink/TopLink full outer join instead left join

On model Card can have or not CardHolder ( 1:1 ), and I would like getting every cards filter by issuer linked to actived cardHolders plus cards without cardHolders, so I need a full outer join. Although the query below translate to left join returning just cards with cardHolders
final ExpressionBuilder builder = new ExpressionBuilder( Card.class );
Expression queryExp = builder.get( "cardIssuer" ).equal( cardIssuer );
queryExp = queryExp.and( builder.get( "cardStatus" ).get( "statusType" ).equal( "ACTIVATED" ) );
queryExp = queryExp.and( builder.getAllowingNull( "cardHolder" )isNull().or(
builder.get( "cardHolder" ).get( "status" ).get( "status" ).equal( "ACTIVE" ) ) );
Expression orderExpression = builder.get( "cardHolder" ).get( "surname" ).descending();
return getMultiple( queryExp, pageable , Card.class, orderExpression );
Translate query is
SELECT COUNT(t0.CARD_ID) FROM CARD t0 LEFT JOIN CARD_HOLDER t3
ON (t3.CARD_HOLDER_ID = t0.CARD_HOLDER_ID), CARD_HOLDER_STATUS t2, CARD_STATUS t1
WHERE (((((t0.CARD_ISSUER_ID = 10006) AND (t1.STATUS_TYPE = 'ACTIVATED')) AND (t2.STATUS = 'ACTIVE'))
AND (t0.CARD_ID IN ('52683','52692')))
AND ((t1.CARD_STATUS_ID = t0.CARD_STATUS_ID) AND (t2.STATUS_ID = t3.STATUS_ID)))
Due to JPA version the outer join is not properly done, so I found a way through native queries
#NamedNativeQueries( {
#NamedNativeQuery( name = Card.USER_DIRECTORY_BASE,
query = "select * from card c full outer join card_holder ch on c.card_holder_id = ch.card_holder_id "
+ "where c.CARD_ISSUER_ID = ?1 and c.card_status_id = 1 and ( ch.STATUS_ID = 1 or c.CARD_HOLDER_ID is null) "
+ "order by ch.FORENAME asc",
resultClass = Card.class ),
#NamedNativeQuery( name = Card.USER_DIRECTORY_BASE_COUNT,
query = "select count(*) from card c full outer join card_holder ch on c.card_holder_id = ch.card_holder_id "
+ "where c.CARD_ISSUER_ID = ?1 and c.card_status_id = 1 and ( ch.STATUS_ID = 1 or c.CARD_HOLDER_ID is null) "
+ "order by ch.FORENAME asc" )
} )
And getting results
Query query = em.createNamedQuery( Card.USER_DIRECTORY_BASE);
query.setParamenter(1,10000);
query.getResultList();

converting SQL join with group by and MAX to Linq

I have Created following query in sql but i am not able to find out how to implement StatusAndTrackingNotes table join in my linq:
SELECT *
FROM [Application] APP
join User USR on APP.ApplicationId = USR.UserApplicationId
join
(Select MAX(TrackingDate) as MaxDateTD,TrackingApplicationId
From StatusAndTrackingNotes
where TrackingLoanType = 1 and ((TrackingStatusCode <= 52 and TrackingStatusCode >= 50) or TrackingStatusCode = 62)
group by TrackingApplicationId) MTND on APP.ApplicationId = MTND.TrackingApplicationId
join Details DTL on APP.ApplicationId = DTL.ApplicationId
join ApplicationFees AF on APP.ApplicationId = AF.ApplicationId
where APP.LatestStatus = 'F' and DTL.Type = 1 and DTL.FundingDate >= '2011-06-01' and DTL.FundingDate <= '2013-06-30'
and AF.FirstRefPaidDate is not null
Kindly help me with the syntax.First i was using using simple query with joins and then
([Linq Query]).GroupBy(i => i.TrackingApplicationId).Select(g => g.OrderByDescending(c => c.TrackingDate).FirstOrDefault());
but it doesnt return any result. Kindly help.
Thanks in advance
I would solve it by creating StatusAndTrackingNotes as separate query and join and group it to the "main query". I.e:
var trackingQuery =
from t in statusAndTrackingNotes
where t.TrackingLoanType == 1 && (t.TrackingStatusCode <= 52 && t.TrackingStatusCode >=50) || t.TrackingStatusCode == 62
group t by t.TrackingApplicationId into trackings
select new
{
TrackingApplicationId = trackings.Key,
MaxDate = trackings.Max(t => t.TrackingDate)
};
var appQuery =
from app in Application
join t in trackingQuery on app.ApplicationId equals t.TrackingApplicationId
/* other joins here */
select new
{
app,
t.MaxDate,
};

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 to SQL query taking forever

Ok, first I thought I had a problem with how I was querying things. But apparently the problem lies in how linq translates my query to sql.
Here's my linq:
var items = (from p in ctx.bam_Prestatie_AllInstances
join q in ctx.bam_Zending_AllRelationships on p.ActivityID equals q.ReferenceData
join r in ctx.bam_Zending_AllInstances on q.ActivityID equals r.ActivityID
orderby p.LastModified descending
where r.PrestatieOntvangen >= vanaf && r.PrestatieOntvangen <= tm
select new Data.BAMPrestatieInstance
{
Aanvaard = p.PrestatieAanvaard,
Contactnummer = r.ContactNr,
Identificatie = p.Identificatie,
Foutmelding = ((p.Foutmelding == "" || p.Foutmelding == null) && p.PrestatieAanvaard == null) ? "De prestatie is bezig met verwerkt te worden." : p.Foutmelding.Replace("\r\n", " "),
Ontvangen = p.PrestatieZendingOntvangen,
Uitvoerdatum = p.Uitvoerdatum.Replace('-', '/'),
Zender = r.Zender,
PrestatieCode = p.PrestatieCode,
ZendingsNr = r.Zendingnummer.ToString(),
GroepsAanvaarding = r.Identificatie
}).Take(100);
Which gets translated in:
SELECT TOP (100) [t3].[Zender], [t3].[ContactNr] AS [Contactnummer], [t3].[Identificatie], [t3].[value] AS [Uitvoerdatum], [t3].[PrestatieZendingOntvangen] AS [Ontvangen], [t3].[PrestatieAanvaard] AS [Aanvaard], [t3].[value2] AS [Foutmelding], [t3].[PrestatieCode], [t3].[value3] AS [ZendingsNr], [t3].[Identificatie2] AS [GroepsAanvaarding]
FROM (
SELECT [t2].[Zender], [t2].[ContactNr], [t0].[Identificatie], REPLACE([t0].[Uitvoerdatum], #p0, #p1) AS [value], [t0].[PrestatieZendingOntvangen], [t0].[PrestatieAanvaard],
(CASE
WHEN (([t0].[Foutmelding] = #p2) OR ([t0].[Foutmelding] IS NULL)) AND ([t0].[PrestatieAanvaard] IS NULL) THEN CONVERT(NVarChar(3800),#p3)
ELSE REPLACE([t0].[Foutmelding], #p4, #p5)
END) AS [value2], [t0].[PrestatieCode], CONVERT(NVarChar,[t2].[Zendingnummer]) AS [value3], [t2].[Identificatie] AS [Identificatie2], [t2].[PrestatieOntvangen], [t0].[LastModified]
FROM [dbo].[bam_Prestatie_AllInstances] AS [t0]
INNER JOIN [dbo].[bam_Zending_AllRelationships] AS [t1] ON [t0].[ActivityID] = [t1].[ReferenceData]
INNER JOIN [dbo].[bam_Zending_AllInstances] AS [t2] ON [t1].[ActivityID] = [t2].[ActivityID]
) AS [t3]
WHERE ([t3].[PrestatieOntvangen] >= #p6) AND ([t3].[PrestatieOntvangen] <= #p7)
ORDER BY [t3].[LastModified] DESC
As you can see, first it selects EVERYTHING and then it takes the top 100 and does the where. Why is this? Why can't it directly do the top 100, I think the problem why my queries run so long is because of this. Is there a better way to construct my linq query then?
Thanks
Try this:
var items = from p in ctx.bam_Prestatie_AllInstances.OrderByDesc(p => p.LastModified).Take(100)
join q in ctx.bam_Zending_AllRelationships on p.ActivityID equals q.ReferenceData
join r in ctx.bam_Zending_AllInstances on q.ActivityID equals r.ActivityID
where r.PrestatieOntvangen >= vanaf && r.PrestatieOntvangen <= tm
select new Data.BAMPrestatieInstance
{
Aanvaard = p.PrestatieAanvaard,
Contactnummer = r.ContactNr,
Identificatie = p.Identificatie,
Foutmelding = ((p.Foutmelding == "" || p.Foutmelding == null) && p.PrestatieAanvaard == null) ? "De prestatie is bezig met verwerkt te worden." : p.Foutmelding.Replace("\r\n", " "),
Ontvangen = p.PrestatieZendingOntvangen,
Uitvoerdatum = p.Uitvoerdatum.Replace('-', '/'),
Zender = r.Zender,
PrestatieCode = p.PrestatieCode,
ZendingsNr = r.Zendingnummer.ToString(),
GroepsAanvaarding = r.Identificatie
};
Since the sort applies only to your first table, I'd try to force the order by and take 100 to be applied before the join.