Question

My goal with this clause is to list the employees that live in San Fran but work in Silicon Valley. Right now my clause is working to find out which employees live in San Fran, but I am not sure how to join the two lists of EmployeeList and WorkInfo in order to take the employees that live in San Fran and find out which of these names also work in Silicon Valley.

Here's what I have so far in my clause:

for $x in /EmpDatabase/PersonList/Contents/Person
where $x/City='San Fran'
order by $x/Name
return $x/Name

And here's my XML data file:

<EmpDatabase>
<PersonList Type="Employee">
<Title Value="Employee List"/>
<Contents>
<Person>
    <Name>Susan L. Anderson</Name>
    <City>San Fran</City>
    <Gender>F</Gender>
</Person>
<Person>
    <Name>Dan L. Brady</Name>
    <City>Sacramento</City>
    <Gender>M</Gender>
</Person>
<Person>
    <Name>Peter K. Chen</Name>
    <City>San Fran</City>
    <Gender>M</Gender>
</Person>
</Contents>
</PersonList>

<CompanyList Type="Company">
<Title Value="Company List"/>
<Contents>
<Company>
    <Name>Google</Name>
    <City>Silicon Valley</City>
</Company>
<Company>
    <Name>Riot</Name>
    <City>LA</City>
</Company>
</Contents>
</CompanyList>

<InfoList Type="Works">
<Title Value="Works List"/>
<Contents>
<Works>
    <Name>Susan L. Anderson</Name>
    <Company>Google</Company>
    <Salary>48000</Salary>
</Works>
<Works>
    <Name>Dan L. Brady</Name>
    <Company>Google</Company>
    <Salary>42000</Salary>
</Works>
<Works>
    <Name>Peter K. Chen</Name>
    <Company>Riot</Company>
    <Salary>53000</Salary>
</Works>
</Contents>
</InfoList>
</EmpDatabase>

Is natural join the right way to go about this? How is natural join written in XQuery? Do I need to write a separate clause in a different file to list the employees that work in Silicon Valley and then somehow join the results of both clauses?

Any help is greatly appreciated!

Was it helpful?

Solution

I renamed $x to $person to give it a more meaningful name.

You could formulate an implicit join, but it's easier to formulate what you're actually looking for:

for $person in /EmpDatabase/PersonList/Contents/Person
(: retrieve company $person is working for :)
let $works := /EmpDatabase/InfoList/Contents/Works[Name=$person/Name]
where $person/City='San Fran'
(: See if the company has a department in Silicon Valley :)
where /EmpDatabase/CompanyList/Contents/Company[Name=$works/Company and City='Silicon Valley']
order by $person/Name
return $person/Name

If you prefer a "classic" join, just use multiple for loops:

for $person in /EmpDatabase/PersonList/Contents/Person
for $works in /EmpDatabase/InfoList/Contents/Works
for $company in /EmpDatabase/CompanyList/Contents/Company
where $person/City='San Fran'
where $person/Name=$works/Name
where $works/Company=$company/Name
where $company/City='Silicon Valley'
order by $person/Name
return $person/Name
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top