How to left join tables in LINQ TO SQL to get associated records - sql

I have a linq to sql statement where I am doing join with a bunch of tables , but I need to left join a table as we are not sure if there be any associated records.
We are left joing as we are not sure if every purchase will have a file associated.
Purchase Join - Invc
Purchase Join - FileStore FileStore##Entity
select * from Purchase p
join Invc i on i.Invc_ID = p.Invc_ID
left join FileStore##Entity fe on p.Purchase_ID = fe.Entity_ID
left join FileStore fs on fs.FileStore_ID = fe.FileStore_ID
where p.Purchase_ID = 53
My current linq to sql works for the regular join , how can I left join the file store and store entity table
PurchaseEntity purchase = (from p in TransactionalDbContext.Purchase
join i in TransactionalDbContext.Invc
on p.InvcId equals i.InvcId
where d.Purchase_Id == id
select new DisputeEntity
{
Purchase_Id = p.Purchase_Id,
InvcId = i.InvcId,
SubmittedDate = d.SubmitDt,
InvcNum = i.InvcNum
// get the file elements by left join file
}).FirstOrDefault();

You can easily perform left or right joins by playing with the DefaultIfEmpy method.
Following your example:
from p in dbContext.Purchases
join i in dbContext.Invc on p.InvcId equals i.InvcId
join fe in dbContext.FileStoreEntities.DefaultIfEmpty() on p.Purchase_ID equals fe.Entity_ID
join fs in dbContext.FileStores.DefaultIfEmpty() on fe.FileStore_ID equals fs.FileStore_ID

Related

Problem with the joining of SQL tables via relationships

I am currently having problems trying the run a query for some tables.
Below is what I am trying to do, I just can't seem to get it to work.
I have also duplicated constituent and gifts to show you the relations between soft credit and gifts/constituents
Link to Table Relations Image
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
INNER JOIN dbo.Constituent Constituent
ON Constituent.id = Gifts.constituent_id
INNER JOIN dbo.SplitGifts SplitGifts
ON SplitGifts.giftid = Gifts.id
LEFT JOIN dbo.SoftCredit SoftCredit
ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Constituent Constituent_1
ON Constituent_1.id = SoftCredit.constituentid
INNER JOIN dbo.Gifts Gifts_1
ON Gifts_1.id = SoftCredit.giftid
INNER JOIN dbo.Package Package
ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
Basically, I want the
amount and gift_aid_amount from [SplitGifts]
Constituent Name & lookup_id from [constituent] to show up for all Gifts however if a soft credit exists for that gift I need it to get the same fields via the [SoftCredit] table -> Gifts -> SplitGifts -> Fields
You could try if the query below works.
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
LEFT JOIN dbo.SoftCredit SoftCredit ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Gifts Gifts_1 ON
Gifts_1.id = SoftCredit.giftid OR
(SoftCredit.giftid IS NULL AND Gifts_1.id = Gifts.id)
INNER JOIN dbo.Constituent Constituent ON
Constituent.id = SoftCredit.constituentid OR
(SoftCredit.constituentid IS NULL AND Constituent.id = Gifts_1.constituent_id)
INNER JOIN dbo.SplitGifts SplitGifts ON SplitGifts.giftid = Gifts_1.id
INNER JOIN dbo.Package Package ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
It joins back to table Gifts (using alias Gifts_1) on the gift reference in SoftCredit or to itself if there is no SoftCredit.
Table Constituent is joined in a similar fashion: it joins on the value of SoftCredit.constituentid and when NULL, it falls back to Gifts_1.constituent_id.
All next joins regarding the gift should refer to Gifts_1 then.
I have not tested it though. But it might give you a hint in a possible solution direction.

How to join a same table with two tables?

I want to create an Oracle database view :
create or replace force view view_ind_pta (indi_code, nat_indi_code, indi_unite, indi_symbole, indi_lib, indi_cible, pta_intitule, indi_resp,
indi_source_info, user_code, peri_mes_code, peri_mes_lib, pta_parent, deleted,obj_intitule,pta_action)
as
select distinct
i.indi_code,
i.nat_indi_code,
i.indi_unite,
i.indi_symbole,
to_char(i.indi_lib) as indi_lib,
i.indi_cible,
concat(concat(to_char(a.pta_ref),' - '),to_char(a.pta_intitule)) as pta_intitule,
i.indi_resp,
to_char(i.indi_source_info) as indi_source_info,
u.user_code,
i.peri_mes_code ,
pm.peri_mes_lib ,
concat(concat(to_char(p.pta_ref),' - '),to_char(p.pta_intitule)) as pta_parent,
i.deleted ,
to_char(o.obj_intitule) as obj_intitule,
concat(concat(to_char(action.pta_ref),' - '),to_char(action.pta_intitule)) as pta_action
from
indicateur i
left join acteur_saisie_indicateur ai on ai.indi_code = i.indi_code
left join acteur_verif_indicateur avi on avi.indi_code = i.indi_code
left join utilisateur u on ( ai.user_code = u.user_code and avi.user_code = u.user_code)
left join objectif o on i.obj_code = o.obj_code
left join pta a on o.pta_code = a.pta_code
left join pta action on a.pta_pta_code = action.pta_code
left join pta p on action.pta_pta_code = p.pta_code
left join periodicite_mesure pm on pm.peri_mes_code = i.peri_mes_code
where p.pta_definitif = 3;
In the view there is the table utilisateur which I want to join with the two tables acteur_saisie_indicateur and acteur_verif_indicateur. I tried the and operator , but I think it is not a good idea because the query will return rows only when there are joined rows in both tables ! Although this is not necessary : I want the query to return rows even if only one table has joined rows. So how to join these three tables ?
We can include the same table in a FROM clause more than once. All we need to do is use different aliases to distinguish the instances:
left join utilisateur uai
on ai.user_code = uai.user_code
left join utilisateur uavi
on avi.user_code = uavi.user_code
The other thing you need to do is handle table's columns in the view's projection. You want to display the utilisateur values regardless of which instance the values come from, say by using nvl() or the industry standard coalesce()
coalesce(uai.user_code, uavi.user_code) as user_code
You need to join the table twice:
left join acteur_saisie_indicateur ai on ai.indi_code = i.indi_code
left join acteur_verif_indicateur avi on avi.indi_code = i.indi_code
left join utilisateur u on ai.user_code = u.user_code
left join utilisateur u2 on avi.user_code = u2.user_code

Oracle (Netsuite) SQL one join limit results

I have an oracle SQL query and a slight problem. I need to check if an item has a PO# that it has at least 1 line item. The query below works however it returns a result for each line of transaction_lines and I need only une result. PS I tried DISTINCT but get an ODBC error.
SELECT ITEMS.NAME, INVENTORY_NUMBER.INVENTORY_NUMBER, INVENTORY_NUMBER.ON_HAND_COUNT, ITEMS.SALESDESCRIPTION, CONDITION.LIST_ITEM_NAME,
BRAND_PARTNER.LIST_ITEM_NAME, PPROGRAM.LIST_ITEM_NAME, ENTITY.NAME, PO.TRANSACTION_NUMBER, INVENTORY_NUMBER.RECEIVED_COST, ITEMS.SALESPRICE, IR.TRANSACTION_NUMBER,
INVENTORY_SOURCE.LIST_ITEM_NAME, LOCATIONS.NAME, INVENTORY_NUMBER.RECEIPT_DATE, PO.INTERNAL_MEMO, INVENTORY_NUMBER.REFERENCE_, TEST_RESULTS.LIST_ITEM_NAME,
INVENTORY_NUMBER.TEST_FILE_LINK, INVENTORY_NUMBER.CONNECT_TRADE_ID, INVENTORY_NUMBER.SOLD_DATE, INVENTORY_NUMBER.SOLD_PRICE, INVENTORY_NUMBER.MEMO, ITEMS.UPC_CODE, ITEMS.MPN,
ITEMS.ITEM_ID, INVENTORY_NUMBER.CLEI, INVENTORY_NUMBER.CERTIFICATION_REF_ID
FROM INVENTORY_NUMBER
INNER JOIN ITEMS ON INVENTORY_NUMBER.ITEM_ID = ITEMS.ITEM_ID
INNER JOIN TRANSACTIONS AS PO ON INVENTORY_NUMBER.PURCHASE_ORDER_ID = PO.TRANSACTION_ID
INNER JOIN TRANSACTIONS AS IR ON INVENTORY_NUMBER.ITEM_RECEIPT_ID = IR.TRANSACTION_ID
INNER JOIN TRANSACTION_LINES ON PO.TRANSACTION_ID = TRANSACTION_LINES.TRANSACTION_ID
INNER JOIN ENTITY ON TRANSACTIONS.ENTITY_ID = ENTITY.ENTITY_ID
INNER JOIN CONDITION ON INVENTORY_NUMBER.CONDITION_ID = CONDITION.LIST_ID
INNER JOIN BRAND_PARTNER ON INVENTORY_NUMBER.BRAND_PARTNER_ID = BRAND_PARTNER.LIST_ID
INNER JOIN PPROGRAM ON INVENTORY_NUMBER.PROGRAM_ID = PPROGRAM.LIST_ID
INNER JOIN INVENTORY_SOURCE ON INVENTORY_NUMBER.INVENTORY_SOURCE_ID = INVENTORY_SOURCE.LIST_ID
INNER JOIN LOCATIONS ON INVENTORY_NUMBER.LOCATION_ID = LOCATIONS.LOCATION_ID
INNER JOIN TEST_RESULTS ON INVENTORY_NUMBER.TEST_RESULTS_ID = TEST_RESULTS.LIST_ID
WHERE INVENTORY_NUMBER.ON_HAND_COUNT IS NOT NULL AND ((INVENTORY_NUMBER.PURCHASE_ORDER_ID IS NULL) OR (INVENTORY_NUMBER.PURCHASE_ORDER_ID IS NOT NULL AND TRANSACTION_LINES.TRANSACTION_LINE_ID IS NOT NULL))
you could also remove the join to the transaction_lines and instead of tl.TRANSACTION_LINE_ID IS NOT NULL use an exists clause
and exists (select 1 from transaction lines tl
where tl.transaction_id = po.transaction_id)
I would suggest using a GROUP BY to help limit your results. You could also if you are interacting with transactions in your query you must always remember that without limiting results based on the "main line" you will receive the header record and then a record for each individual line item.
If you were doing this with a saved search you could put the criteria as "main line = true". Since I don't understand your query entirely I can't advise where to put this limitation in.

SQL Query to retrieve single record per filter

I have the following query:
SELECT min(salesorder.SOM_SalesOrderID) AS salesorder,
Item.IMA_ItemID,
Item.IMA_ItemName,
Customer.CUS_CorpName,
WK.WKO_WorkOrderID,
min(WK.WKO_OrigRequiredDate),
WK.WKO_WorkOrderTypeCode,
min(WK.WKO_RequiredDate),
max(WK.WKO_LastWorkDate),
min(wk.WKO_RequiredQty),
wk.WKO_MatlIssueDate,
min(SalesOrderDelivery.SOD_RequiredQty),
Item.IMA_ItemTypeCode,
Item.IMA_OnHandQty,
min(SalesOrderDelivery.SOD_PromiseDate),
min(WO.woo_operationseqID) AS seqid
FROM SalesOrder
INNER JOIN SalesOrderLine ON SalesOrder.SOM_RecordID = SalesOrderLine.SOI_SOM_RecordID
INNER JOIN SalesOrderDelivery ON SalesOrderLine.SOI_RecordID = SalesOrderDelivery.SOD_SOI_RecordID,
WO.
INNER JOIN Item ON SalesOrderLine.SOI_IMA_RecordID = Item.IMA_RecordID
INNER JOIN WKO wk ON Item.IMA_ItemID = WK.WKO_ItemID
INNER JOIN Customer ON SalesOrder.SOM_CUS_RecordID = Customer.CUS_RecordID
INNER JOIN woo WO ON WO.WOO_WorkOrderID = WK.WKO_WorkOrderID
WHERE wk.WKO_StatusCode = 'Released'
AND WO.WOO_StatusCode IS NULL
AND SalesOrderDelivery.SOD_ShipComplete = 'false'
GROUP BY WK.WKO_WorkOrderID,
Item.IMA_ItemID,
Item.IMA_ItemName,
Customer.CUS_CorpName,
WK.WKO_WorkOrderTypeCode,
wk.WKO_MatlIssueDate,
Item.IMA_ItemTypeCode,
Item.IMA_OnHandQty
I need 1 record returned for each wk.wko_workorderid. There is a field that is not included that I'm not sure how to get. I need to retrieve the woo.woo_workcenterid that corresponds to min(WO.woo_operationseqID)as seqid. I cannot include it in the general query since there are multiple workcenterids in the table and I only want the specific one that is part of the min operation sequence record.
Any help would be appreciated.

SQL Server update with joins

I am trying to update a date in a table, based off of a MAX(date) in another table. To get the correct data to link up, I have to do 2 inner joins and 2 left outer joins.
I can select the correct data, it returns a Guid (PersonId) and the Date.
I have to use this information to update my original table. I am having trouble getting this to work, I still getting syntax errors.
update tblqualityassignments as assign
inner join tblrequirementteams as team on assign.guidmemberid = team.guidmemberid
set assign.dtmQAPCLed = dtmTaken
from
(
select reg.guidpersonid, max(certs.dtmTaken) as dtmTaken from tblqualityassignments as assign
inner join tblrequirementteams as team on assign.guidmemberid = team.guidmemberid
inner join tblregisteredusercerts as reg on team.guidpersonid = reg.guidpersonid
left outer join tblcerttaken as certs on certs.guidcertid = reg.guidcertid
left outer join tblCodesCertType as types on types.intcerttypeid = certs.intcerttypeid
where types.intcerttypeid = 1
and assign.guidmemberid = team.guidmemberid
group by reg.guidpersonid as data
)
where data.guidpersonid = team.guidpersonid
Assuming you are using SQL Server for this, then this should work:
UPDATE A
SET A.dtmQAPCLed = dtmTaken
FROM tblqualityassignments AS A
INNER JOIN tblrequirementteams as T
ON A.guidmemberid = T.guidmemberid
INNER JOIN (select reg.guidpersonid, max(certs.dtmTaken) as dtmTaken
from tblqualityassignments as assign
inner join tblrequirementteams as team
on assign.guidmemberid = team.guidmemberid
inner join tblregisteredusercerts as reg
on team.guidpersonid = reg.guidpersonid
left outer join tblcerttaken as certs
on certs.guidcertid = reg.guidcertid
left outer join tblCodesCertType as [types]
on [types].intcerttypeid = certs.intcerttypeid
where [types].intcerttypeid = 1
and assign.guidmemberid = team.guidmemberid
group by reg.guidpersonid) data
ON T.guidpersonid = data.guidpersonid