**1. CURRENT STATUS**

We expanded our previous XML query proposal to include all of the
query-related nodes that we currently use, both for formulation of the
query and for the returned query results. We added those items that we
understood were needed by our SPIN collaborators. We retained the
general format of our previous proposal, but have added support for
expressions, additional data elements, and the ability to returning
patient level data (a sample of which are now being provided by the
Boston Spin system. Many of the expression and condition tag names, and
much of that XML format, were inspired by the W3C "MathML" project at
<http://www.w3.org/Math/>. MathML defines a format for expressing
mathematical content in XML so for the mathematical parts of the SPIN
syntax we stayed very close to MathML.

The XML schema file for the query schema syntax is attached to this
email and has been submitted to the SPIN web site.

**2.0 CONVENTIONS**

For clarity and brevity, we have not included the XML \<query\> and
\</query\> tags in the examples within the main body of this document.
We have also omitted the \<identity\> and \<evaluationSettings\> nodes
from those examples.

For readability and consistency, our tag names are in "camel case"
format. For example, the tag \<startsWith\> has a capital "W" to
designate the beginning of the second word.

We have not included any XML namespace identifiers in our examples.
Nothing in the schema precludes the use of name space identifiers and we
believe we should include them in the final product.

Our XML Schema uses a "composition" design strategy for defining and
extending XML data types. Refer to the web site
<http://ww.xfront.com/composition-versus-subclassing.html> for a
description of the composition XML schema design strategy and of how it
is easily married with XSL-driven applications. Composition makes it
possible to add new functions, operators, and/or conjunctions without
tearing apart the entire schema. For example, we have defined an
"abstract" XML element named "conjunction". All logical expressions are
defined using that "conjunction" element reference. The XML elements
"and" and "or" have been defined as concrete elements which are
substitutable everywhere "conjunction" appears in the schema. The "and"
and "or" elements do not themselves appear anywhere else. Thus, we can
add another conjunction, like "xor"; by simply defining the new
conjunction element as substitutable for the same abstract "conjunction"
element and "xor" will become available throughout our schema.

Composition also makes it possible to locally "extend" portions of the
query schema without affecting anyone else.

**3.0 OVERVIEW OF QUERY XML FORMAT**

The entire query definition is contained within the query node. Its
overall structure is:

\<query\>

\<identity\>...\</identity\>

\<evaluationSettings\>...\</evaluationSettings\>

\<conditions\>...\</conditions\>

\<returnStatistics\>...\</returnStatistics\>

\<returnData\>...\</returnData\>

\</query\>

The identity node documents who and when the query was created and
evaluated. The evaluationSettings node can contain global parameter
settings that affect overall query evaluation. The conditions node
specifies the query search conditions; that is, what we are looking for.
The results of the query evaluation are returned in the returnStatistics
and/or the returnData node, as requested.

**3.1 identity**

The identity node defines by whom and when the query was initiated and,
optionally, who and when it was replied to. Its contents are purely for
bookkeeping and debugging purposes.

**3.2 evaluationSettings**

The evaluationSettings node defines global query execution parameter
settings. We do not currently have any such parameter settings, but have
anticipated that need.

**3.3 conditions**

The conditions node defines the criteria for identifying the data of
interest. It may contain a single condition or a tree of logically
connected condition nodes. Section 4.1 shows a query with a single
condition. Its basic structure is:

\<conditions\>

\<condition\>...\</condition\>

\</conditions\>

Section 4.2 contains a sample query with multiple condition nodes.
Consider one very simple example. Suppose we named our conditions "A",
"B", and "C" and wanted to represent the logic "If A and (B or C)". Our
conditions node would be structured as follows:

\<conditions\>

\<AND\>

\<condition name="A"\>...\</condition\>

\<OR\>

\<condition name="B"\>...\</condition\>

\<condition name="C"\>...\</condition\>

\</OR\>

\</AND\>

\</conditions\>

**3.3.1 condition**

The condition node is the "heart" of the XML query syntax. It is
required in each conditions, breakdownVariable, dependentVariable, and
returnVariable node. Each condition node defines a clinical variable and
the criteria for searching the values or reports stored for that
variable within a SPIN database. In other words, the condition node
tells us what data to search and what subset of that data is of
interest. For example, a simple condition node can tell us to find all
pathology reports with a diagnosis of prostate cancer, PSA values
greater than 4, Hispanic patients, patients who have survived more than
5 years after being diagnosed with breast cancer, etc. We will discuss
more complex search criteria later on.

Each condition variable is defined with the combination of a code and a
coding system "name", very much like an HL7 "CE" data value. The coding
system "name" identifies the range of legal codes (and other) aspects of
that coding system. Our current queries use LOINC codes for variable
definitions, and at past meetings we have committed to using LOINC codes
for most of this space. However, the query syntax described in this
document is not tied to any specific coding system. No matter what the
code and code system, each SPIN node must be able to map from that code
into the appropriate, searchable data structures in its own database.
Thus, SPIN provides a common "external" data view for query builders,
but permits each SPIN node to have "internal" data structures of its own
design.

Most of the SPIN content can be considered as a clinical variable from
the point of view of the query syntax. These variables such as the
variable "Surgical Pathology Tissue Dx") map to a set of value tuples.
Each tuple consists of a many "component" values, such as physiologic
time (the specimen collection time for a specimen based observation)
value, specimen tissue type, etc. For those of you familiar with HL7,
you could picture this as a concatenation of many of the fields in the
HL7 OBX and OBR segments. Searches based on these variables can test any
or all of the components of the tuple. For example, we might want to
limit the search to "Surgical Pathology Tissue Dx" reports whose
physiologic time is before Jan 1, 1997, whose coded value equals
"adenocarcinoma" and whose tissue type equals "prostate". Our current
query schema provides the following searchable components codedValue,
numericValue, physiologicTime, interpretationCode, textReport,
tissueType, bodySite, and collectionMethod. Our XML design strategy
makes it simple to extend this list of searchable components to such
items as reporting date-time as the committee sees fit. We wish to
emphasize that this SPIN query syntax view of the world does not require
that the underlying data base structure conform to this view. (Indeed
ours does not)

Some query variables e.g., age, or gender, might be considered as
constant attributes of the patient, in which case they might be
considered 1-tuples with only one component, namely the value. We will
identify such special variables by an attribute included in the table of
SPIN searchable variables.

The general format of a condition node is:

\<condition\>

transformation

\<variable.../\>

pre-transformation criteria (optional)

/transformation

post-transformation criteria (optional)

\</condition\>

The syntax for the transformation and criteria nodes is defined later in
this document.

**3.3.1 Searching for Existence of Data**

The simplest possible condition searches for the existence of values for
the specified variable. That simple search does not care what values are
recorded in the database, when the values were recorded, etc.

\<condition\>

\<all\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\</all\>

\</condition\>

**3.3.2 Post-Transformation Criteria**

Our format for specifying criteria and expressions was inspired by the
MathML standard. The query schema definition fully describes this
syntax, but we will illustrate the key features in this document.

We start with a simple example. Suppose we are interested in only
adenocarcinomas of the prostate. We amend our previous example as
follows:

\<condition\>

\<all\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\</all\>

\<and\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0033572"

name="Prostate"

system="UMLS"/\>

\<or\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0001418"

name="Adenocarcinoma"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0007130"

name="Adenocarcinoma, Mucinous"

system="UMLS"/\>

\</eq\>

\</or\>

\</and\>

\</condition\>

Here, we search for the coded value component of the "Surgical Pathology
Tissue Dx" to be either "Adenocarcinoma " or "Adenocarcinoma, Mucinous"
and the specimen tissue type to be "Prostate". Besides the equal
operator eq, the propose syntax also supports comparison tags neq, lt,
leq, gt, geq, contains, and matches (regular expression matching).

The conjunction tags and and or can be used to create very complex
logical search criteria. For example, suppose we want to modify our
previous search to return only those diagnoses before June 1, 2003 and
we are only interested in diagnoses from specimens obtained via biopsy
or excision. We amend our example as follows:

\<condition\>

\<all\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\</all\>

\<and\>

\<lt\> \<variableComponent\>physiologicTime\</variableComponent\>

\<ctime\>2003-06-01\</ctime\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0033572"

name="Prostate"

system="UMLS"/\>

\<or\>

\<eq\>

\<variableComponent\>collectionMethod\</variableComponent\>

\<ccode code="C0005558"

name="Biopsy"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>collectionMethod\</variableComponent\>

\<ccode code="C0015252"

name="Excision"

system="UMLS"/\>

\</eq\>

\</or\>

\<or\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0001418"

name="Adenocarcinoma"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0007130"

name="Adenocarcinoma, Mucinous"

system="UMLS"/\>

\</eq\>

\</or\>

\</and\>

\</condition\>

Please note that we **do** permit more than two comparisons within a
single and or or node.

**3.3.3 Value Subset Transformations**

Sometimes we want to limit (subset) our search to certain significant
values stored for a variable, but we cannot express that as a component
comparison. For example, we may be interested in the last recorded value
for each patient or the highest recorded value for each patient. Our
queries support the transformation operators first, last, max, and min
for identifying those significant values. The following XML query tests
to see if the patient's last surgical pathology report diagnosis was a
prostate cancer diagnosis and was before June 1, 2003.

\<condition\>

\<last\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\</last\>

\<and\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0033572"

name="Prostate"

system="UMLS"/\>

\<lt\>

\<variableComponent\>physiologicTime\</variableComponent\>

\<ctime\>2003-06-01\</ctime\>

\</lt\>

\<or\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0001418"

name="Adenocarcinoma"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0007130"

name="Adenocarcinoma, Mucinous"

system="UMLS"/\>

\</eq\>

\</or\>

\</and\>

\</condition\>

We have changed our condition so that instead of searching all of the
"Surgical Pathology Tissue Dx" values in the database, we search just
the most recent (last) "Surgical Pathology Tissue Dx" values for each
patient. Be aware that multiple reports may have the same physiologic
time and/or value so the transformations first, last, max, and min may
generate a list of values per patient rather than a single value per
patient.

**3.3.4 Pre-Transformation Criteria**

The previous search condition may still not be what we want. Suppose we
want to know if the last prostate cancer diagnosis was before June 1,
2003. We do not care if there were other cancer diagnoses after that. We
do this by moving the comparisons that test for "prostate cancer
diagnosis" so that they occur **before** the last transformation. That
query is expressed as:

\<condition\>

\<last\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\<and\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0033572"

name="Prostate"

system="UMLS"/\>

\<or\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0001418"

name="Adenocarcinoma"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0007130"

name="Adenocarcinoma, Mucinous"

system="UMLS"/\>

\</eq\>

\</or\>

\</and\>

\</last\>

\<lt\>

\<variableComponent\>physiologicTime\</variableComponent\>

\<ctime\>2003-06-01\</ctime\>

\</lt\>

\</condition\>

Now our query searches for the last of the prostate cancer diagnoses and
then checks to see if the recorded physiologic time of that diagnosis
was before June 1, 2003. This is quite different than our previous
example.

**3.3.5 Value Calculation Transformations**

The transformations documented above reduce the set of
observations/values to a smaller set of observations/values. The
transformations count, mean, and sdev (for standard deviation) take the
set of observations/values and reduce it to a single value. These
transformations generate numeric values so only use the numericValue
component can be evaluated in post-transformation criteria.
Pre-transformation criteria can still check any variable component.

**3.5 returnStatistics**

The returnStatistics node defines the statistical data to be returned
for those patients whom matched the criteria specified in the conditions
node. The general format of the returnStatistics node is:

\<returnStatistics\>

\<breakdownVariable\>...\</breakdownVariable\> (optional)

\<dependentVariable\>...\</dependentVariable\> (optional)

\<cells\> (only in query response)

\</returnStatistics\>

When one or more breakdownVariable nodes exist, statistics are returned
in multiple cell nodes within the cells node. Each cell represents a
single cell within the N-way cross tabulation table, where N is the
number of breakdownVariable's. Dependent variables statistics are
aggregated and reported within each cell. If no breakdownVariable's are
specified, the cells node is returned with just a count and one
statistics node for each dependent variable. Some examples will help
demonstrate this format.

**3.5.1 breakdownVariable**

Each breakdownVariable specifies one dimension of the cross tabulation
table. The general format of a breakdownVariable node is:

\<breakdownVariable name="myname" ordinal="1"\>

\<variableComponent\>...\</variableComponent\>

\<condition\>...\</condition\>

\<breakdown\>...\</breakdown\>

\</breakdownVariable\>

The query user can name the breakdown variable so that is appears as
desired in the query response. That name is saved in the name attribute
in the breakdownVariable node. Each breakdown variable is also assigned
an integer value that represents is position in the N-way cross
tabulation. This ordinal attribute value is always between 1 and N.

Each data value to be aggregated is defined by a variableComponent and
condition node. The condition node specifies the database variable whose
values are to be aggregated and any criteria for the specific values of
interest. The variable component tells the query evaluator software
which component (the value, physiologic time, abnormality status,
specimen tissue type, etc.) of the variable values is to be aggregated.

Within the breakdown node, we define the statistical bins into which the
data will be aggregated. The following examples illustrate this.

Let us do a breakdown of the patient's last PSA values into the
intervals 0.0-4.0, 4.1-10.0, 10.1-20.0, and \>20.0 ng/ml. The query XML
syntax for numeric intervals comes directly from the W3C MathML
specification. Our query breakdownVariable node might appear as follows:

\<breakdownVariable name="Last PSA" ordinal="1"\>

\<variableComponent\>numericValue\</variableComponent\>

\<condition\>

\<last\>

\<variable code="2857-1\"

name=\"PSA SerPl Qn\"

system="LN" /\>

\<last\>

\</condition\>

\<breakdown\>

\<cutpoint name="Normal PSA"\>

\<interval closure="closed-closed"\>

\<cn\>0.0\</cn\>

\<cn\>4.0\</cn\>

\</interval\>

\</cutpoint\>

\<cutpoint\>

\<interval closure="open-closed"\>

\<cn\>4.0\</cn\>

\<cn\>10.0\</cn\>

\</interval\>

\</cutpoint\>

\<cutpoint\>

\<interval closure="open-closed"\>

\<cn\>10.0\</cn\>

\<cn\>20.0\</cn\>

\</interval\>

\</cutpoint\>

\<cutpoint\>

\<interval closure="open-closed"\>

\<cn\>20.0\</cn\>

\<maxvalue/\>

\</interval\>

\</cutpoint\>

\</breakdown\>

\</breakdownVariable\>

We have specified aggregation by the numeric value component of the last
PSA value. Last PSA values are aggregated into the intervals:

\[0 - 4.0\]

(4.0 - 10.0\]

(10.0 - 20.0\] and

\>20.0.

There are not any recorded values \<0, so every aggregated value appears
in one of these intervals, with one exception. Patients with no recorded
PSA values, but who match the query conditions, are aggregated into the
"Missing Value" bin.

In addition to aggregating numeric value into intervals, we can create
breakdowns for variables with coded results. The following example shows
how to generate a breakdown by specimen tissue type for coded surgical
pathology diagnoses.

\<breakdownVariable name="Pathology Report Tissue Type" ordinal="2"\>

\<variableComponent\>tissueType\</variableComponent\>

\<condition\>

\<all\>

\<variable code="34574-4\"

name=\"Surgical Pathology Tissue Dx\"

system="LN" /\>

\<all\>

\</condition\>

\<breakdown max="10"/\>

\</breakdownVariable\>

When we ask for a breakdown of the code component, by default we get
each code returned in a separate statistical bin. By specifying
max="10*",* we limit the number of aggregated statistical bins to 10. If
the actual data values would result in more than 10 bins being created,
we create a single bin labeled "Miscellaneous". We keep combing the
lowest frequency bin into "Miscellaneous" until we achieve the bin limit
of 10. The bin limit of 10 includes both the "Missing value" and
"Miscellaneous" bins.

When the query has been evaluated, this node is returned with each of
those bins explicitly defined, as follows:

\<breakdownVariable name="Pathology Report Tissue Type" ordinal="2"\>

\<variableComponent\>tissueType\</variableComponent\>

\<condition\>

\<all\>

\<variable code="34574-4\"

name=\"Surgical Pathology Tissue Dx\"

system="LN" /\>

\<all\>

\</condition\>

\<breakdown max="10"\>

\<cutpoint ordinal="1" name="Missing Value"/\>

\<cutpoint ordinal="2" name="Breast"\>

\<ccode code="C0006141" name="Breast" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="3" name="Colon"\>

\<ccode code="C0009368" name="Colon" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="4" name="Gallbladder"\>

\<ccode code="C0016976" name="Gallbladder" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="5" name="Integumentary system"\>

\<ccode code="C0037267" name="Integumentary system" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="6" name="lymph nodes"\>

\<ccode code="C0024204" name="lymph nodes" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="7" name="Prostate"\>

\<ccode code="C0033572" name="Prostate" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="8" name="Uterine cervix-Anatomy"\>

\<ccode code="C0007874" name="Uterine cervix-Anatomy" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="9" name="Uterus"\>

\<ccode code="C0042149" name="Uterus" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="10" name="Miscellaneous"/\>

\</breakdown\>

\</breakdownVariable\>

The ordinal values are referenced in the returned statistical cell
nodes, as you will see in subsequent examples.

One other cutpoint feature bears special mention. We permit more than
one value to be aggregated into a single statistical bin. Suppose we
want to combine the two bins "Uterus" and "Uterine cervix-Anatomy" (see
example above) into a single statistical bin. We might generate the
following query XML:

\<breakdownVariable name="Pathology Report Tissue Type" ordinal="2"\>

\<variableComponent\>tissueType\</variableComponent\>

\<condition\>

\<all\>

\<variable code="34574-4\"

name=\"Surgical Pathology Tissue Dx\"

system="LN" /\>

\<all\>

\</condition\>

\<breakdown max="10"\>

\<cutpoint name="Uterus"\>

\<ccode code="C0007874"

name="Uterine cervix-Anatomy"

system="UMLS"/\>

\<ccode code="C0042149"

name="Uterus"

system="UMLS"/\>

\</cutpoint\>

\</breakdown\>

\</breakdownVariable\>

We have specified that we want the two CUI codes listed above aggregated
into a single statistical bin named "Uterus". Note that we did not have
to explicitly list all of the bins that will get created, just the ones
we want combined. The technique can also be applied to intervals for
numeric data.

**3.5.2 dependentVariable**

The dependentVariable syntax is a subset of the breakdownVariable
syntax. The general format for a dependentVariable node is:

\<dependentVariable name="myname" ordinal="3"\>

\<variableComponent\>...\</variableComponent\>

\<condition\>...\</condition\>

\</dependentVariable\>

Note that no breakdown can be specified for a dependentVariable.

**3.5.3 cells**

The actual statistics are returned within the cells node. It consist of
an overall count plus a list of the individual statistical cell nodes
for the N-way cross tabulation. Empty cells are **not** returned in
order to minimize the volume of returned data. The general format for
the cells node is:

\<cells\>

\<count\>...\</count\>

\<cell\>...\</cell\> (repeats as many times as needed)

\</cells\>

The count node contains the overall number of cases returned. Each cell
represents a single statistical bin within the N-way cross tabulation.
The cells node is only present in the query response.

**3.5.3.1 cell**

Each cell contains the total count of the number of cases that were
categorized in that statistical cell, the "subscript" of the cell
location in the N-way cross tabulation table, and the list of statistics
computed for each dependent variable value within that statistical cell.
The general format for a cell node is:

\<cell\>

\<count\>...\</count\>

\<breakdownVariable\>...\</breakdownVariable\> (repeats as needed)

\<dependentVariable\>...\</dependentVariable\> (repeats as needed)

\</cell\>

The count is the number of items falling into this bin. Each
breakdownVariable is a single subscript into the N-way cross tabulation
table. Each dependentVariable node contains the aggregated statistical
information (count, sum, mean, standard deviation, max, min) for one
dependent variable.

Let us make an example with two breakdown variables and a single
dependent variable. The returnStatistics node might look as follows:

\<returnStatistics\>

\<breakdownVariable name="Last PSA" ordinal="1"\>

\<variableComponent\>numericValue\</variableComponent\>

\<condition\>

\<last\>

\<variable code="2857-1\"

name=\"PSA SerPl Qn\"

system="LN" /\>

\<last\>

\</condition\>

\<breakdown\>

\<cutpoint ordinal="1" name="Missing Value"/\>

\<cutpoint ordinal="2" name="Normal PSA"\>

\<interval closure="closed-closed"\>

\<cn\>0.0\</cn\>

\<cn\>4.0\</cn\>

\</interval\>

\</cutpoint\>

\<cutpoint ordinal="3" name="(4.0 -- 10.0\]"\>

\<interval closure="open-closed"\>

\<cn\>4.0\</cn\>

\<cn\>10.0\</cn\>

\</interval\>

\</cutpoint\>

\<cutpoint ordinal="4" name="(10.0 -- 20.0\]"\>

\<interval closure="open-closed"\>

\<cn\>10.0\</cn\>

\<cn\>20.0\</cn\>

\</interval\>

\</cutpoint\>

\<cutpoint ordinal="5" name="\>20.0"\>

\<interval closure="open-closed"\>

\<cn\>20.0\</cn\>

\<maxvalue/\>

\</interval\>

\</cutpoint\>

\</breakdown\>

\</breakdownVariable\>

\<breakdownVariable name="Pathology Report Tissue Type" ordinal="2"\>

\<variableComponent\>tissueType\</variableComponent\>

\<condition\>

\<all\>

\<variable code="34574-4\"

name=\"Surgical Pathology Tissue Dx\"

system="LN" /\>

\<all\>

\</condition\>

\<breakdown max="10"\>

\<cutpoint ordinal="1" name="Missing Value"/\>

\<cutpoint ordinal="2" name="Breast"\>

\<ccode code="C0006141" name="Breast" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="3" name="Colon"\>

\<ccode code="C0009368" name="Colon" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="4" name="Gallbladder"\>

\<ccode code="C0016976" name="Gallbladder" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="5" name="Integumentary system"\>

\<ccode code="C0037267" name="Integumentary system" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="6" name="Liver"\>

\<ccode code="C0023884" name="Liver" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="7" name="lymph nodes"\>

\<ccode code="C0024204" name="lymph nodes" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="8" name="Prostate"\>

\<ccode code="C0033572" name="Prostate" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="9" name="Uterus"\>

\<ccode code="C0042149" name="Uterus" system="UMLS"/\>

\<ccode code="C0007874" name="Uterine cervix-Anatomy" system="UMLS"/\>

\</cutpoint\>

\<cutpoint ordinal="10" name="Miscellaneous"/\>

\</breakdown\>

\</breakdownVariable\>

\<dependentVariable ordinal="3"\>

\<variableComponent\>numericValue\</variableComponent\>

\<condition\>

\<last\>

\<variable code="21841-2\"

name=\"Age at Cancer Dx\"

system="LN" /\>

\<last\>

\</condition\>

\</dependentVariable\>

\<cells\>

\<count\>100\</count\>

\<cell\>

\<count\>3\</count\>

\<breakdownVariable ordinal="1" cutpoint="1"/\>

\<breakdownVariable ordinal="2" cutpoint="1"/\>

\<dependentVariable ordinal="3"

count="2" sum="140" max="90" min="50" sdev="160"/\>

\</cell\>

\<cell\>

\<count\>47\</count\>

\<breakdownVariable ordinal="1" cutpoint="1"/\>

\<breakdownVariable ordinal="2" cutpoint="2"/\>

\<dependentVariable ordinal="3"

count="31" sum="1752" max="90" min="10" sdev="73.54"/\>

\</cell\>

\<cell\>

\<count\>36\</count\>

\<breakdownVariable ordinal="1" cutpoint="1"/\>

\<breakdownVariable ordinal="2" cutpoint="3"/\>

\<dependentVariable ordinal="3"

count="27" sum="1930" max="90" min="10" sdev="175.47"/\>

\</cell\>

\<cell\>

\<count\>9\</count\>

\<breakdownVariable ordinal="1" cutpoint="2"/\>

\<breakdownVariable ordinal="2" cutpoint="3"/\>

\<dependentVariable ordinal="3"

count="9" sum="720" max="80" min="40" sdev="25.54"/\>

\</cell\>

\<cell\>

\<count\>5\</count\>

\<breakdownVariable ordinal="1" cutpoint="4"/\>

\<breakdownVariable ordinal="2" cutpoint="3"/\>

\<dependentVariable ordinal="3"

count="5" sum="341" max="80" min="40" sdev="18.2"/\>

\</cell\>

\</cells\>

\</returnStatistics\>

The requested statistics are breakdowns by last PSA and pathology report
tissue type. The dependent variable is "age at cancer diagnosis". In
this example, the last PSA value has been aggregated into 5 statistical
bins:

1=Missing Value,

2=(0.0-4.0\],

3=(4.0-10.0\],

4=(10.0-20.0\], and

5=\>20.

The pathology tissue type has been aggregated into ten statistical bins:

1=Missing Value,

2=Breast,

3=Colon,

4=Gallbladder,

5=Integumentary system,

6=Liver,

7=lymph nodes,

8=Prostate,

9=Uterus, and

10=Miscellaneous.

Examine the last cell returned in the example. It says 5 of the patients
matching the query conditions fell into breakdown bin 4 (10.0-20.0\] for
"last PSA" and breakdown bin 3 for tissue type "Colon". The dependent
variable information shows that the average age at cancer diagnosis for
that group was 341/5 (68.2) years of age.

**3.6 returnData**

The returnData node defines the raw data to be returned for those cases
that matched the criteria specified in the conditions node. In the
query, the returnData node contains a list of returnVariable nodes, each
specifying a single data item to be returned as raw data. In the query
response (after query evaluation), the returnVariable node also contains
a data node with the actual raw data values.

**3.6.1 returnVariable**

Each returnVariable node contains a single condition node, specifying
the database variable and component to be returned as raw data. The
condition node has been described in previous sections of this document.

**3.6.2 data**

The data node is a container for a list of dataRow nodes. Each dataRow
node contains the raw data returned for a single case. The query schema
defines the format of the dataRow node as "any", meaning we cannot fix
its format ahead of time. The format of each dataRow is determined by
the list of returnVariable values that the query asked for.

**4.0 ADDITIONAL QUERY EXAMPLES AND DESCRIPTIONS**

**4.1 Single Query Variable and Single Returned Variable**

Our first query asks for a breakdown of "patient race" for all patients
with a tumor of the "prostate".

\<conditions\>

\<condition\>

\<all\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\</all\>

\<and\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0033572"

name="Prostate"

system="UMLS"/\>

\<or\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0001418"

name="Adenocarcinoma"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0007130"

name="Adenocarcinoma, Mucinous"

system="UMLS"/\>

\</eq\>

\</or\>

\</and\>

\</condition\>

\</conditions\>

\<returnStatistics\>

\<breakdownVariable name=\"Race\"\>

\<variableComponent\>codedValue\</variableComponent\>

\<condition\>

\<all\>

\<variable code=\"RACE\"

system=\"SPIN_DEMOGRAPHICS\"

name=\"SPIN Patient Race\"/\>

\</all\>

\</condition\>

\</breakdownVariable\>

\</returnStatistics\>

The conditions node defines the query used to identify the cases for
which data will be returned. The returnStatistics node defines the data
that is returned for those cases. In this example, we are looking for
cancers of the prostate and returning a breakdown of all of those
patients by race. Notice that the RACE variable is defined in much the
same manner as any other database variable.

**4.2 Compound Query Variables and Criteria**

This conditions node specifies a search for patients with a cancer of
the prostate or the liver within the last year and whose last PSA value
is less than or equal to 4.0

\<conditions\>

\<AND\>

\<condition\>

\<all\>

\<variable code="34574-4"

name="Surgical Pathology Tissue Dx"

system="LN"/\>

\</all\>

\<and\>

\<or\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0033572"

name="Prostate"

system="UMLS"/\>

\<eq\> \<variableComponent\>tissueType\</variableComponent\>

\<ccode code="C0023884"

name="Liver"

system="UMLS"/\>

\</or\>

\<or\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C000148"

name="Adenocarcinoma"

system="UMLS"/\>

\</eq\>

\<eq\>

\<variableComponent\>codedValue\</variableComponent\>

\<ccode code="C0007130"

name="Adenocarcinoma, Mucinous"

system="UMLS"/\>

\</eq\>

\</or\>

\</and\>

\</condition\>

\<condition\>

\<last\>

\<variable code="2857-1\"

name=\"PSA SerPl Qn\"

system="LN" /\>

\<last\>

\<le\>

\<variableComponent\>numericValue\</variableComponent\>

\<cn\>4.0\</cn\>

\</le\>

\</condition\>

\</AND\>

\</conditions\>

**5.0 FURTHER DISCUSSION**

We have not specified units for any numeric values (quantities) in the
query XML.

Our current query server only returns aggregated statistical
information. We have allocated and defined a format for returning raw
data in our schema, but have no current experience at actually using
that feature. Boston has such experience.

In order to have all SPIN query server nodes understand each other's
queries, we need to coordinate the names we use in the code system
attribute. HL7 version 2 suggests using "LN" for LOINC, "I9" for
ICD-9-CM, etc. We would suggest using HL7 vs. 2.x specified names for
coding systems where they exist and defining explicitly listing the
coding systems that SPIN will support across nodes.

Our tag names are open for discussion, but we think they have evolved to
a fairly understandable form. We do think it is a good idea to use
MathML tag names for the functions and concepts that it supports,
because they come from a respected external source and have been tested
by time.

We need to consider special functions for dates and times, such as
functions to do date arithmetic and to convert time intervals into days,
months, or years.

SPIN needs to decide on a common code set for patient gender, race, and
marital status if we want our nodes to understand each other's data. The
HL7 version 2.x code tables might be a good starting point.

Any software that is used to create queries will need to know which
components are available for which variables. For example, the
"dateOfBirth" variable is just a date. The "Serum Potassium" variable
may have the numericValue, physiologicTime, interpretationCode,
textReport, tissueType, bodySite, and collectionMethod component values
recorded. SPIN will want that information housed by, and distributable
from, all of its "super nodes".