I need to write a LINQ TO XML query, which queries two XML files exported from Access database tables. The original Access DB query looks like this:
SELECT
(
[TableB].[Code] Is Null,[TableA].[Code],
LCase(Left([TableA].[Code],1)) & ":" & [TableB].[code]
) AS Code,
Trim
(
[TableB].[Description] & " " & [TableA].[Description]
) AS Description
FROM TableA LEFT JOIN TableB
ON TableA.Code = TableB.SubProduct;
When I convert it to LINQ to XML, I have the problem of the right part of the left join is not available. My LINQ look like this:
Dim results = _
From a In TableA.Descendants("Product")
Group Join b In TableB.Descendants("Product")
On a.Element("Code").Value Equals b.Element("SubProduct").Value Into leftJoinGroup Group
From p In leftJoinGroup.DefaultIfEmpty
Select New With
{
I DON KNOW HOW TO WRITE IT
}
Both tables have the column named "Code". However, the variable TableB seems to be unavailable inside my Selectclause. I only have a and p available so I can't get the Code from TableB (b). How should I do that?
I just started using linq myself and ran into this issue last week. This was very helpful for me http://msdn.microsoft.com/en-us/vstudio/bb688088.aspx but here is an example of how to perform a left outer join in vb.net http://msdn.microsoft.com/en-us/vstudio/bb737909#lojoin.
In your example tableB is being stored into leftJoinGroup which your selecting from using p. To get values from tableB you will need to select from p and since your trying to concatenate the columns from both tableA and tableB, I would check if tableB record is null.
Dim results = From a In TableA.Descendants("Product") Group Join b In TableB.Descendants("Product") _
On a.Element("Code").Value Equals b.Element("SubProduct").Value Into leftJoinGroup = Group _
From p In leftJoinGroup.DefaultIfEmpty() _
Select New With { _
.Code = If(p Is Nothing, a.Element("Code").Value, String.Format("{0}:{1}", Left(a.Element("Code").Value.ToLower(), 1), p.Element("Code").Value)), _
.Description = If(p Is Nothing, a.Element("Description").Value, String.Format("{0} {1}", p.Element("Description").Value, a.Element("Description").Value))}
Here is an example of your code above, I didn't tested it. I've used this code when joining datatables not xdocuments. Sorry if this isn't clear this my first post here.
Related
I have a query in which I select multiple values. To create my form.
The results look like this :
the last Column [Candidat Nom] is a drop down list with an other query (lets call it Query 1) that select my drop down list values.
The selection is good and is what I'm looking for. Except I get the same value for all lines when they need to be different.
To simplify
let's take the following exemple
I have the following candidate that wants to join for the following job (Represented with their ID).
As we can see 2 candidates wants job N° 12. and 1 candidate for each other job.
What I get
All candidates are listed for every job.
What I want
What I actually did
is I put the following query (Query 1) on my column.
SELECT T_SALARIE.SALARIE_nom & " " & T_SALARIE.SALARIE_prenom AS Candidat Nom
FROM T_EMPLOI INNER JOIN (T_SALARIE INNER JOIN (T_SALARIE_EMPLOI LEFT JOIN T_STATUT_EMPLOI ON T_SALARIE_EMPLOI.SALARIE_EMPLOI_statut_id = T_STATUT_EMPLOI.STATUT_EMPLOI_id) ON T_SALARIE.SALARIE_NNI = T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni) ON T_EMPLOI.EMPLOI_identifiant = T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
WHERE (((T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*valid*" Or (T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*décidé*") AND ((T_EMPLOI.EMPLOI_entreprise_id)=1));
This gave me the result I want but with the issue I mentioned previously (Same result for each line)
So
I thought I needed a new Criteria.
I added one, where It's going to select the candidate when the two "emploi ID" of my actual table (Shown before) and the one helping me select the candidates are equal.
With the following query:
SELECT T_SALARIE.SALARIE_nom & " " & T_SALARIE.SALARIE_prenom AS Candidat, T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
FROM T_EMPLOI INNER JOIN (T_SALARIE INNER JOIN (T_SALARIE_EMPLOI LEFT JOIN T_STATUT_EMPLOI ON T_SALARIE_EMPLOI.SALARIE_EMPLOI_statut_id = T_STATUT_EMPLOI.STATUT_EMPLOI_id) ON T_SALARIE.SALARIE_NNI = T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni) ON T_EMPLOI.EMPLOI_identifiant = T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
WHERE (((T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*valid*" Or (T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*décidé*") AND ((T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant)=[R_Select_COMOB]![ACTION_identifiant_emploi]));
But I keep on getting the following pop up that asks me to enter a Job ID
So how can I make the query for each line compare and select the right values?
I hope I was clear in explaining. If not please let me know so that I can add more details.
Thank you !
Thanks to your help and specially #June7 for his propositions, I found a solution regarding my problem :
I added a criteria to select values based on JobID that I wasn't selecting in the first hand.
And then based on the column (jobID) select the values needed
here is my final query :
SELECT
[SALARIE_nom] & " " & [SALARIE_prenom] & " (" & [SALARIE_NNI] & ")" AS Salarié, T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni, T_SALARIE_EMPLOI.SALARIE_EMPLOI_id, T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
FROM
(T_STATUT_EMPLOI INNER JOIN T_SALARIE_EMPLOI ON T_STATUT_EMPLOI.STATUT_EMPLOI_id = T_SALARIE_EMPLOI.SALARIE_EMPLOI_statut_id) LEFT JOIN R_Select_Salarie ON T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni = R_Select_Salarie.SALARIE_NNI
WHERE
(((T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant)=[Formulaires]![F_COMOB]![ACTION_identifiant_emploi]) AND ((T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*validé*") AND ((T_SALARIE_EMPLOI.SALARIE_EMPLOI_Entreprise) Like "*RTE*"));
And Then to update my values for each line. I added a VBA code that requery on input.
Private Sub ACTION_Candidats_P_Enter()
ACTION_Candidats_P.Requery
End Sub
With that my problem is solved.
I want query LINQ to LEFT JOIN TWO TABLES get results like SQL exactly
(show results like the picture even the row empty yellow line)
My code:
Dim qJoint = From tSum In lstSUM Group Join tbnk In lstBank On tbnk.ID_BANK Equals tSum.ID_BANK _
Into tResult = Group From tbnk In tResult.DefaultIfEmpty Select tbnk.ID_BANK, tbnk.ABRIGER, tbnk.NomBank_AR, tSum.Montant_Facture
Little Problem Try Code:
Dim result= from v in VW_sum_bybank
join b in tbl_bank on v.id_bank equals b.id_bank into jj from kk in jj.DefaultIfEmpty()
select
V_id_bank=v.id_banl,
Code_bank=v.Code_bank,
NOMBANK=v.NOMBANK,
ABRG=v.ABRG,
b_id_bank=kk.ID_bank,
sommeFAC=kk.sommeFAC
I have two tables: t1 and t3 and I have following sql query:
select t1.*, t3.* from t1 left join t3 on t1.f1=t3.f1
t1 contains 30k records, t3 has only 10. The matching field is f1.
t1 has 5 fields, t3 has 2 fields.
With the above query I get the 30k records + 10 field values also like this:
t1.f1, t1.f2, t1.f3, t1.f4, t1.f5, t3.f1, t3.f2
The records are so, that there is a matching only in case of the first 10 records. So after that, t3.f1 and t3.f2 are empty values.
Now, I would like to write a query in LINQ, wich produces this result:
Dim JoinedResult = LeftTable.GroupJoin(RightTable, Function(LeftTableRow) LeftTableRow(FieldIndexInLeftTable), _
Function(RightTableRow) RightTableRow(FieldIndexInRightTable), _
Function(LeftTableRow, RightTableRow) New With {LeftTableRow, RightTableRow.DefaultIfEmpty(Function(Item) IIf(Item Is Nothing, Nothing, Item))})
As you see, I'm trying to tell LINQ, that if any item of the RightTableRow is empty, then I need the field value in this case too, with an empty value.
But vb says: Anonymous type member name can be inferred only from a simple or qualified name with no arguments.
It is important, that the fields of table t3 can be various, so defining an empty value for t3.f1 and t3.f2 is not an option. I need to define an empty value (null) for all fields in t3, if there is no matching record.
It can be, that in t3 there is more matching record to a row in t1, so I must use SelectMany too, but how?
Thanks.
EDIT:
Dim JoinedResult = LeftTable.GroupJoin(RightTable, Function(LeftTableRow) LeftTableRow(FieldIndexInLeftTable), _
Function(RightTableRow) RightTableRow(FieldIndexInRightTable), _
Function(LeftTableRow, RightTableRow) _
New With {LeftTableRow, RightTableRow}). _
SelectMany(Function(Row) _
Row.RightTableRow.DefaultIfEmpty().Select(Function(RightT) _
New With {Row.LeftTableRow, _
Key .rt = RightT.Select(Function(Item) IIf(Item Is Nothing, String.Empty, Item)).ToArray}))
with this the error message disappear, but I get a null exception at runtime, which is obv. results from the fact, that RighT is - except the first 10 records - null.
You should look at this link :
http://msdn.microsoft.com/en-us/library/vstudio/bb397895.aspx
Your code should look to follow :
var query =
from left in LeftTable
join right in RightTable on right.FieldIndexInRightTable equals left.FieldIndexInLeftTable
into gj
from subpet in gj.DefaultIfEmpty()
select new {Your fields };
Could somebody help me complete this linq left outer join query so that the second column of the right table (tempData) is contained in the result set even though it may be null?
sortedData = From cs In mbCustomSort
Order By cs(0)
Group Join entry In tempData On cs(joinColumn) Equals entry(0) Into Group
From last In Group.DefaultIfEmpty _
Select New With {.groupField = cs(joinColumn)}
Sorry, I write in C#, but how about:
var sortedData = from cs in mbCustomSort orderby cs.JoinColumn
join entry in tempData on cs.JoinColumn equals entry.OtherJoinColumn into Group
from subentry in Group.DefaultIfEmpty()
select new { groupField = cs.JoinColumn };
LINQPad's default processing doesn't allow for item(fieldno), so I used actual field names in data repurposed from here, including adding a new row in Mbc with no corresponding OrderId in Mbtd. This works for me:
From cs In Mbcs _
Order By cs.Catalogid _
Group Join entry In mbtds On cs.OrderId Equals entry.OrderId Into Group _
From last In Group.DefaultIfEmpty _
Select cs.OrderId, last.Ocardtype
And by "works" I mean the row I added appears with a null Ocardtype (as well as another row where Ocardtype was already null).
(Edited)
The From last In Group turns the outer join into an inner join. This does not happen when you continue with the Group variable:
sortedData = From cs In mbCustomSort
Order By cs(0)
Group Join entry In tempData On cs(joinColumn) Equals entry(0) Into Group
Select New With {.groupField = cs(joinColumn),
.col2 = Group(1).RightColumn }
Change RightColumn by the property of "In-memory Query" object.
I'm trying to make a query which has the same field in table A & table B. Then table B has the same field as table C. I want to left join all tables on table A. Is this possible? If yes, how close is my code to doing it?
Try
objConn = DBAccess.GetConnection
strBlder.Append("SELECT ")
strBlder.Append("FLD_NM, DATA_TYPE_CD, XML_PATH_TX, UPDT_USER_ID_NR, DOC_TMPL_FLD_ID_NR ")
strBlder.Append("FROM ")
strBlder.Append("LLC.[LLCW10_DCTMPFLD_TB] LEFT JOIN LLC.[DataMapTool_FieldMapping] ")
strBlder.Append("ON LLC.[LLCW10_DCTMPFLD_TB].DOC_TMPL_FLD_ID_NR = LLC.[DataMapTool_FieldMapping].DocumentTemplateFieldID ")
strBlder.Append("& LEFT JOIN LLC.[DataMapTool_FieldMapping] ")
strBlder.Append("ON LLC.[DataMapTool_FieldMapping].FieldMappingStatusID = LLC.[DataMapTool_FieldMappingStatus].FieldMappingStatusID ")
strBlder.Append("ORDER BY FLD_NM ;")
dsData = DBAccess.ExecuteDataTable(objConn, CommandType.Text, strBlder.ToString())
'execute non query - takes sp name
The error you are getting(after removing the &) is because LLC.[DataMapTool_FieldMapping] is repeated and thats a problem. Instead of your from clause try something like:
FROM (LLC.[LLCW10_DCTMPFLD_TB] LEFT JOIN LLC.[DataMapTool_FieldMapping] ON LLC.[LLCW10_DCTMPFLD_TB].DOC_TMPL_FLD_ID_NR = LLC.[DataMapTool_FieldMapping].DocumentTemplateFieldID)
LEFT JOIN LLC.[DataMapTool_FieldMappingStatus] ON LLC.[DataMapTool_FieldMappingStatus].FieldMappingStatusID = LLC.[DataMapTool_FieldMapping].FieldMappingStatusID
Note that the LLC.[DataMapTool_FieldMapping] is referenced in the first join and then only the .FieldMappingStatusID field is referenced in the second join. Your initial query would have been trying to add the same table to the query twice without giving it an alias which confuses the query analyzer.
Basically the new from clause will attach the first two tables together then attach the third table onto the result of the first join.
Looks good to me, but there is that strange & before the LEFT JOIN LLC.[DataMapTool_FieldMapping] ... take that out.