I've this query that i'm trying to put as linq:
select *
from stuff
inner join stuffowner so on so.stuffID = stuff.stuffID
left outer join (select min(loanId) as loanId, stuffownerId from loan
where userid = 1 and status <> 2 group by stuffownerId) t on t.stuffownerid = so.stuffownerid
left outer join loan on t.LoanId = loan.LoanId
when this is done, I would like to do a linq Group by to have Stuff has key, then stuffowners + Loan as value.
I can't seem to get to a nice query without sub query (hence the double left outer).
So basically what my query does, is for each stuff I've in my database, bring the owners, and then i want to bring the first loan a user has made on that stuff.
I've tried various linq:
from stuff in Stuffs
join so in StuffOwners on stuff.StuffId equals so.StuffId
join tLoan in Loans on so.StuffOwnerId equals tLoan.StuffOwnerId into tmpJoin
from tTmpJoin in tmpJoin.DefaultIfEmpty()
group tTmpJoin by new {stuff} into grouped
select new {grouped, fluk = (int?)grouped.Max(w=> w.Status )}
This is not good because if I don't get stuff owner and on top of that it seems to generate a lot of queries (LinqPad)
from stuff in Stuffs
join so in StuffOwners on stuff.StuffId equals so.StuffId
join tmpLoan in
(from tLoan in Loans group tLoan by tLoan.StuffOwnerId into g
select new {StuffOwnerId = g.Key, loanid = (from t2 in g select t2.LoanId).Max()})
on so.StuffOwnerId equals tmpLoan.StuffOwnerId
into tmptmp from tMaxLoan in tmptmp.DefaultIfEmpty()
select new {stuff, so, tmptmp}
Seems to generate a lot of subqueries as well.
I've tried the let keyworkd with:
from tstuffOwner in StuffOwners
let tloan = Loans.Where(p2 => tstuffOwner.StuffOwnerId == p2.StuffOwnerId).FirstOrDefault()
select new { qsdq = tstuffOwner, qsdsq= (int?) tloan.Status, kwk= (int?) tloan.UserId, kiwk= tloan.ReturnDate }
but the more info i get from tLoan, the longer the query gets with more subqueries
What would be the best way to achieve this?
Thanks
Related
The below code is written to get the all the parent and child relationship and want to understand why the And is not filtering the records but where does.
e.g-
select
s.name,
s.status,
s.start_date_active,
s.end_date_active,
s.salesrep_number,
p.name Parent_name,
p.status Parent_status,
p.start_date_active Parent_start_date_active,
p.end_date_active Parent_end_date_active,
FROM XXX_XX_SALESREPS s
left outer join XXX_XX_SALESREPS p
on s.attribute1 = p.salesrep_id
**and s.attribute1 = '100003916'**
this above query give all the rows from table s and do not filter it on '100003916' . But when i used ..
select
s.name,
s.status,
s.start_date_active,
s.end_date_active,
s.salesrep_number,
p.name Parent_name,
p.status Parent_status,
p.start_date_active Parent_start_date_active,
p.end_date_active Parent_end_date_active,
FROM XXX_XX_SALESREPS s
left outer join XXX_XX_SALESREPS p
on s.attribute1 = p.salesrep_id
**where s.attribute1 = '100003916'**
this query gives me just filter record. Why can anyone please answer it. Thanks in advance.
In your first case and s.attribute1 = '100003916' is part of your join criteria - and since it is left outer join it wont serve as a filter.
I'm trying to build a linq query based on this:
select
SERVICE_REQUEST_CR.SRCR_FK_SR, SERVICE_REQUEST.SR_TX_NAME,
AC_USER.USER_TX_NAME, SERVICE_REQUEST_CR.SRCR_DT_CREATED,
SERVICE_REQUEST_CR_STATUS.SRCRST_TX_DESCRIPTION,
COUNT(SERVICE_REQUEST_PROGRAM.SRPG_FK_SR_ID) as Activities
from
SERVICE_REQUEST_CR
inner join
AC_USER on AC_USER.USER_ID = SERVICE_REQUEST_CR.SRCR_FK_REQUESTOR
inner join
SERVICE_REQUEST_CR_STATUS on SERVICE_REQUEST_CR_STATUS.SRCRST_ID = SERVICE_REQUEST_CR.SRCR_FK_CR_STATUS
inner join
SERVICE_REQUEST on SERVICE_REQUEST.SR_ID = SERVICE_REQUEST_CR.SRCR_FK_SR
inner join
SERVICE_REQUEST_PROGRAM on SERVICE_REQUEST_PROGRAM.SRPG_FK_SR_ID = SERVICE_REQUEST_CR.SRCR_FK_SR
group by
SERVICE_REQUEST_CR.SRCR_FK_SR, SERVICE_REQUEST.SR_TX_NAME,
AC_USER.USER_TX_NAME, SERVICE_REQUEST_CR.SRCR_DT_CREATED,
SERVICE_REQUEST_CR_STATUS.SRCRST_TX_DESCRIPTION,
SERVICE_REQUEST_PROGRAM.SRPG_FK_SR_ID
This is as far as I could come up with:
Dim x = From cr In db.SERVICE_REQUEST_CR
Join usr In db.AC_USER On usr.USER_ID Equals cr.SRCR_FK_REQUESTOR
Join crSt In db.SERVICE_REQUEST_CR_STATUS On crSt.SRCRST_ID Equals cr.SRCR_FK_CR_STATUS
Join sr In db.SERVICE_REQUEST On sr.SR_ID Equals cr.SRCR_FK_SR
Join srProg In db.SERVICE_REQUEST_PROGRAM On srProg.SRPG_FK_SR_ID Equals cr.SRCR_FK_SR
Could anyone give me a help with this? It's the grouping that gets confusing so I just put the joins and the query to keep it simple.
Thanks,
Something like this, but I am not sure about Basic syntax:
Dim x = From cr In db.SERVICE_REQUEST_CR
Join usr In db.AC_USER On usr.USER_ID Equals cr.SRCR_FK_REQUESTOR
Join crSt In db.SERVICE_REQUEST_CR_STATUS On crSt.SRCRST_ID Equals cr.SRCR_FK_CR_STATUS
Join sr In db.SERVICE_REQUEST On sr.SR_ID Equals cr.SRCR_FK_SR
Join srProg In db.SERVICE_REQUEST_PROGRAM On srProg.SRPG_FK_SR_ID Equals cr.SRCR_FK_SR
group new
{
cr.SRCR_FK_SR,
sr.SR_TX_NAME,
usr.USER_TX_NAME,
cr.SRCR_DT_CREATED,
crSt.SRCRST_TX_DESCRIPTION,
srProg.SRPG_FK_SR_ID
}
by new
{
cr.SRCR_FK_SR,
sr.SR_TX_NAME,
usr.USER_TX_NAME,
cr.SRCR_DT_CREATED,
crSt.SRCRST_TX_DESCRIPTION,
srProg.SRPG_FK_SR_ID
} into gr
select new
{
gr.Key.SRCR_FK_SR,
gr.Key.SR_TX_NAME,
gr.Key.USER_TX_NAME,
gr.Key.SRCR_DT_CREATED,
gr.Key.SRCRST_TX_DESCRIPTION,
gr.Key.SRPG_FK_SR_ID,
Activities = gr.Count()
}
I am going to try to use left outer join between Ticket and Membership.
However, it does not display the foreign key of NULL values on Ticket. Could you give me some answer for this what's wrong with this query?
Thanks.
FROM Ticket t, Production pro, Performance per, Price, Price_level, Booking, Customer, Customer_Concession ccons, Membership, Member_concession mcons
WHERE t.performanceid = per.performanceid AND
t.PRODUCTIONID = Price.PRODUCTIONID AND
t.levelId = Price.levelId AND
Price.PRODUCTIONID = pro.PRODUCTIONID AND
Price.levelId = Price_level.levelId AND
Booking.bookingId (+) = t.bookingId AND
Customer.customerId = Booking.customerId AND
ccons.cConcessionId (+) = Customer.cConcessionId AND
Membership.membershipId (+) = t.membershipId AND
Membership.mConcessionId = mcons.mConcessionId
ORDER BY t.ticketId
One potential problem you have is these two conditions:
Booking.bookingId (+) = t.bookingId AND
Customer.customerId = Booking.customerId AND
Since you're doing an outer join to Booking, its columns will appear as NULL when no match is found; but then your doing a normal join to Customer, so those rows will be eliminated since NULL cannot be equal to anything. You may want to change the second line to an outer join as well.
But, I don't know if that's your primary problem, since I don't actually understand exactly what you're asking. What do you mean by "NULL value of the foreign key"? You haven't specified what your foreign keys are.
To expand on Dave's observation, and to give you an example of SQL92 syntax, please please please learn it and get away from Oracle's own outer join syntax.
FROM
TICKET t
JOIN Performance per
ON per.performance_id = t.performance_id
JOIN Production pro
ON pro.produciton_id = t.production_id
JOIN PRICE pr
ON pr.production_id = pro.production_id
AND pr.levelId = t.level_id
JOIN price_level pl
ON pl.levelid = pr.levelid
LEFT OUTER JOIN booking b
on b.booking_id = t.booking_id
LEFT OUTER JOIN customer cus
on cus.customer_id = b.customer_id
LEFT OUTER JOIN customer_concession cons
ON cons.concession_id = cus.concession_id
LEFT OUTER JOIN memebership m
ON M.membership_id = t.membership_id
LEFT OUTER JOIN membership_concession mc
ON mc.mConcession_id = m.mConcession_id
Order by t.ticketid
Im trying to convert a SQL join to LINQ. I need some help in getting the nested join working in LINQ.
This is my SQL query, Ive cut it short just to show the nested join in SQL:
select distinct
txtTaskStatus as TaskStatusDescription,
txtempfirstname+ ' ' + txtemplastname as RaisedByEmployeeName,
txtTaskPriorityDescription as TaskPriorityDescription,
dtmtaskcreated as itemDateTime,
dbo.tblTask.lngtaskid as TaskID,
dbo.tblTask.dtmtaskcreated as CreatedDateTime,
convert(varchar(512), dbo.tblTask.txttaskdescription) as ProblemStatement,
dbo.tblTask.lngtaskmessageid,
dbo.tblMessage.lngmessageid as MessageID,
case when isnull(dbo.tblMessage.txtmessagesubject,'') <> '' then txtmessagesubject else left(txtmessagedescription,50) end as MessageSubject,
dbo.tblMessage.txtmessagedescription as MessageDescription,
case when dbo.tblMessage.dtmmessagecreated is not null then dbo.tblMessage.dtmmessagecreated else CAST(FLOOR(CAST(dtmtaskcreated AS DECIMAL(12, 5))) AS DATETIME) end as MessageCreatedDateTime
FROM
dbo.tblAction RIGHT OUTER JOIN dbo.tblTask ON dbo.tblAction.lngactiontaskid = dbo.tblTask.lngtaskid
LEFT OUTER JOIN dbo.tblMessage ON dbo.tblTask.lngtaskmessageid = dbo.tblMessage.lngmessageid
LEFT OUTER JOIN dbo.tblTaskCommentRecipient
RIGHT OUTER JOIN dbo.tblTaskComment ON dbo.tblTaskCommentRecipient.lngTaskCommentID = dbo.tblTaskComment.lngTaskCommentID
ON dbo.tblTask.lngtaskid = dbo.tblTaskComment.lngTaskCommentTaskId
A more seasoned SQL programmer wouldn't join that way. They'd use strictly left joins for clarity (as there is a strictly left joining solution available).
I've unraveled these joins to produce a hierarchy:
Task
Action
Message
TaskComment
TaskCommentRecipient
With associations created in the linq to sql designer, you can reach these levels of the hierarchy:
//note: these aren't outer joins
from t in db.Tasks
let actions = t.Actions
let message = t.Messages
let comments = t.TaskComments
from c in comments
let recipients = c.TaskCommentRecipients
DefaultIfEmpty produces a default element when the collection is empty. Since these are database rows, a default element is a null row. That is the behavior of left join.
query =
(
from t in db.Tasks
from a in t.Actions.DefaultIfEmpty()
from m in t.Messages.DefaultIfEmpty()
from c in t.Comments.DefaultIfEmpty()
from r in c.Recipients.DefaultIfEmpty()
select new Result()
{
TaskStatus = ???
...
}
).Distinct();
Aside: calling Distinct after a bunch of joins is a crutch. #1 See if you can do without it. #2 If not, see if you can eliminate any bad data that causes you to have to call it. #3 If not, call Distinct in a smaller scope than the whole query.
Hope this helps.
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[ShipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPostalCode], [t0].[ShipCountry]
FROM [Orders] AS [t0]
LEFT OUTER JOIN ([Order Details] AS [t1]
INNER JOIN [Products] AS [t2] ON [t1].[ProductID] = [t2].[ProductID]) ON [t0].[OrderID] = [t1].[OrderID]
can be write as
from o in Orders
join od in (
from od in OrderDetails join p in Products on od.ProductID equals p.ProductID select od)
on o.OrderID equals od.OrderID into ood from od in ood.DefaultIfEmpty()
select o
I have the following Linq statement:
(from order in Orders.AsEnumerable()
join component in Components.AsEnumerable()
on order.ORDER_ID equals component.ORDER_ID
join detail in Detailss.AsEnumerable()
on component.RESULT_ID equals detail.RESULT_ID
where orderRestrict.ORDER_MNEMONIC == "MyOrderText"
select new
{
Mnemonic = detail.TEST_MNEMONIC,
OrderID = component.ORDER_ID,
SeqNumber = component.SEQ_NUM
}).ToList()
I expect this to put out the following query:
select *
from Orders ord (NoLock)
join Component comp (NoLock)
on ord .ORDER_ID = comp.ORDER_ID
join Details detail (NoLock)
on comp.RESULT_TEST_NUM = detail .RESULT_TEST_NUM
where res.ORDER_MNEMONIC = 'MyOrderText'
but instead I get 3 seperate queries that select all rows from the tables. I am guessing that Linq is then filtering the values because I do get the correct values in the end.
The problem is that it takes WAY WAY too long because it is pulling down all the rows from all three tables.
Any ideas how I can fix that?
Remove the .AsEnumerable()s from the query as these are preventing the entire query being evaluated on the server.