Reputation: 3
I'd like to get a list of doctors without ill patients. (ill means with at least one Value
in Outcome
outside MinVal
and MaxVal
)
I've understood that the value is printed twice because there are 2 Exams made by Doctor Stack Overflow.
Moreover in $doc-ill
there are only Doctor
that have an Exam
with the first Outcome
out of range. Instead what I wanted to do is put in $doc-ill
all the Doctor with at least one Outcome
out of range.
Can someone highlight what I am doing wrong?
declare function local:outRange($x as element()) as xs:boolean{
boolean( $x/Value < $x/MinVal or $x/Value > $x/MaxVal )
};
(: List of all doctors :)
let $alldoc := distinct-values(//Exam/Doctor)
(: List of doctors with at least 1 ill patient :)
for $exam in //Exam
let $doc-ill := $exam/Doctor
where some $outc in $exam/Outcome satisfies local:outRange($outc)
return (
(: List of doctors without hill patients :)
let $ok := (
for $doc in $alldoc
return if( some $doc2 in $doc-ill satisfies $doc2 = $doc)
then ()
else( $doc )
)
return <HealthyDoctors> {
$ok
}</HealthyDoctors>
)
A small sample of XML is this:
<Exam>
<Outcome>
<Value>90</Value>
<MinVal>100</MinVal>
<MaxVal>150</MaxVal>
</Outcome>
<Outcome>
<Value>15</Value>
<MinVal>1</MinVal>
<MaxVal>20</MaxVal>
</Outcome>
<Outcome>
<Value>1</Value>
<MinVal>1</MinVal>
<MaxVal>5</MaxVal>
</Outcome>
<Doctor>Stack Overflow</Doctor>
</Exam>
<Exam>
<Outcome>
<Value>190</Value>
<MinVal>100</MinVal>
<MaxVal>150</MaxVal>
</Outcome>
<Outcome>
<Value>10</Value>
<MinVal>1</MinVal>
<MaxVal>5</MaxVal>
</Outcome>
<Doctor>Stack Overflow</Doctor>
</Exam>
<Exam>
<Outcome>
<Value>120</Value>
<MinVal>100</MinVal>
<MaxVal>150</MaxVal>
</Outcome>
<Outcome>
<Value>4</Value>
<MinVal>1</MinVal>
<MaxVal>5</MaxVal>
</Outcome>
<Doctor>Health</Doctor>
</Exam>
<Exam>
<Outcome>
<Value>120</Value>
<MinVal>100</MinVal>
<MaxVal>150</MaxVal>
</Outcome>
<Outcome>
<Value>10</Value>
<MinVal>1</MinVal>
<MaxVal>5</MaxVal>
</Outcome>
<Doctor>OneIll</Doctor>
</Exam>
What I am expecting as a result is:
<HealthyDoctors>
<Doctor>Health</Doctor>
</HealthyDoctors>
Upvotes: 0
Views: 39
Reputation: 6218
I am not sure what a "hill patient" is, but guessing from your code I would say it is an Outcome
element, where the value is outside the minimal or maximum value.
I am not sure about your whole code, as it is very complicated for the result you want to achieve. At first you try to get all doctors with one hill patient and then it seems you want to get the difference of the whole set an the set of doctors with one hill patient to get your actual result. But in fact it is much simpler to simply get all doctors without a hill patient, without all the re-directions:
declare function local:in-range($x as element(Outcome)) as xs:boolean{
xs:int($x/Value) >= xs:int($x/MinVal) and xs:int($x/Value) <= xs:int($x/MaxVal)
};
<HealthyDoctors> {
for $doc in distinct-values(//Exam/Doctor)
where every $outcome in //Exam[Doctor = $doc]/Outcome satisfies local:in-range($outcome)
return <Doctor>{ $doc }</Doctor>
}</HealthyDoctors>
So this code basically says give me every doctor where each Outcome
element he/she is assigned to satisfies all the range requirements. That your outRange
function did not work properly was because the values were compared as strings (i.e. "9" > "10"
), so you have to explicitly cast them to be an int.
Also, I renamed your function to in-range
, because it is XQuery convention to not use camel case, but a hyphen instead.
Upvotes: 1