Class AdvancedCriterionSubquery
- All Implemented Interfaces:
HasHandlers
DSRequest that you use to declare the properties of
a subquery (a fieldQuery or
valueQuery) to be used in AdvancedCriteria.
Subquery definitions are often very compact; only a few properties are permitted for a
client-driven subquery (see "Restrictions on client-driven subqueries", below), and many
use cases can be satisfied specifying just a
dataSource and a
summary function.
Criteria subquery definitions fall into two broad categories:
- Aggregation, where the subquery uses a
SummaryFunctionTypeto aggregate or summarize a related dataset, and then filter on that aggregated or summarized value. For example, orders with more than 10 lines, customers with an average order value more than $1000, UK customers with an outstanding payment more than a week old, etc - Related value, where the subquery selects a value (or, for
inSet-type clauses, a set of values) from a related dataSource and then filters on that value. For example, Products that were not ordered last month, Employees who are based in one of the North American offices, Orders that include a particular category of Product, etc
In ideal circumstances - when both main and subquery dataSources are
SQL DataSources, and a number of other restrictions are
satisfied - subqueries are implemented by incorporating their functionality into a larger
overall SQL query, because this is the most efficient thing to do, and gives the best
performance. See canEmbedSQL for a
description
of the rules and nuances around this.
In cases where we cannot implement subqueries by embedding SQL, they are implemented by
converting the subquery definitions into separate real DSRequests, executing
them, and then combining their results into the wider resultset.
Subquery Overview
Subqueries are used to derive a value to be compared as part of the main query, from a set of related data where there is no way to directly join to a single record (usually because the subquery is summarizing or extracting from a larger dataset). Each subquery must return a single value per record in the main query, because it going to be compared to a single value from each main record (this value either comes directly from the main record, or is derived via afieldQuery)
Because the nature of a subquery is that it is deriving a single value from multiple records, subqueries are often involved in some kind of aggregation (returning a record count, or the minimum value, for example). While this is the most common use of subqueries, it is not the only one - see the "Simple valueQuery" example below.
Whether or not a subquery is aggregating multiple records, it typically needs to be constrained by a join to the outer query. For example, if you were looking for all customers that have placed more than $1000-worth of orders, you would use something like the "Simple aggregating subquery" below. As you will see, that example displays no explicit means of joining the subquery to the outer query, and yet one is obviously necessary because we are looking for the sum of "lineValue" customer-by-customer, not the total sum for all customers.
This join from the subquery to the outer query is applied implicitly by Smart GWT's SQL
engine. It auto-discovers a Relation between the main dataSource and subquery dataSource
by following foreignKey definitions from the subquery
dataSource, until it finds a path to the main dataSource. This auto-discovery usually does
the right thing, but there are two possibilities it does not address:
- There is no direct or indirect Relation from the subquery dataSource to the main
dataSource. This is an unusual case for a subquery - most use use cases call for related
dataSources - but valid cases are conceivable. To cope with this scenario, you set
queryFKto the special value "*none*". Note, if Smart GWT fails to find a path from the subquery dataSource to the main dataSource andqueryFK:"*none*"has not been set, the framework will log a warning and the fetch will fail - There is more than one direct or indirect Relation from the subquery dataSource to the
main dataSource, and you want to use a different one from the one that was auto-discovered.
Again, the solution is to explicitly name the
queryFK- see the documentation for that property for details of the syntax
Since Smart GWT can only make use of a single value as output from a subquery, if your
subquery returns multiple records, we will simply use the first. If the query returns
multiple fields, you can specify the field to use as the subquery output with
queryOutput. If the subquery returns more
than one field and no queryOutput is specified, we will use the first
aggregated (summaryFunction) field, or
the first grouped field if there are no
aggregated fields, or the primaryKey field if there are
also no groupBy fields, or just the first numeric field failing all else.
Note, however, that although we attempt to derive a sensible value, it never makes sense to
return multiple records from a subquery, and it only really makes sense to return multiple
fields if you explicitly identify the correct field with queryOutput.
Ideally, for the sake of clarity, return a single record, and either have that record
contain a single field, or specify queryOutput
Restrictions on client-driven subqueries
For security reasons, subqueries inrequests that came from the
client-side are only permitted to specify a handful of properties. These properties are
sufficient to allow the full power of the subquery feature to be used, without allowing any
of the much broader set of general properties associated with the DSRequest
superclass. The properties that can be set in a client-driven subquery are just those that
are documented as direct properties of the AdvancedCriterionSubquery class -
specifically canEmbedSQL,
criteria,
dataSource,
groupBy,
operationId,
queryFK,
queryOutput, and
summaryFunctions
For DSRequests that originally came from the server, it is possible to have a
subquery that specifies any DSRequest property. Many of these would only have
any relevance or effect if the subquery was run separately rather than embedded (as
described above and in the canEmbedSQL doc).
If you need to do this, look in the server Javadoc for
DSRequest.setAllowArbitrarySubqueries(boolean)
Finally, note that it is possible to switch off the ability to use subqueries altogether,
either per-DataSource, or globally by
setting
the allowCriteriaSubqueries flag in your server.properties file:
allowCriteriaSubqueries: false
Examples
Subqueries are quite hard to describe in narrative text, but the following examples demonstrate their use and should make things clearer
Simple aggregating subquery
This example uses afieldQuery to select all Order records for customer
1234, where the order total (sum of all the order line values) is greater than $1000.
Order.fetchData({
_constructor: "AdvancedCriteria", operator: "and", criteria: [
{fieldName: "customerNumber", operator: "equals", value: 1234},
{
fieldQuery: {
dataSource: "OrderLine",
summaryFunctions: {lineValue: "sum"}
}, operator: "greaterThan", value: 1000
}
]
});
Simple valueQuery
This example uses avalueQuery to derive the employeeNumber of a manager when
we only know the email address of that manager, so we can find out who reports to her.
This example shows how to use additional criteria within a subquery. It also demonstrates
the relatively rare situation where no join to the outer dataSource is required (hence the
declaration of queryFK: "*none*")
Employee.fetchData({
_constructor: "AdvancedCriteria", operator: "and", criteria: [
{
fieldName: "reportsTo",
operator: "equals",
valueQuery: {
dataSource: "Employee",
queryFK: "*none*",
criteria: { operator: "and", criteria: [
{fieldName: "email", operator: "equals", value: 'mpatterson@classicmodelcars.com'}
]
}
}
}
]
});
More complex aggregation example
This example uses both afieldQuery and a valueQuery to select
all US-based customers who placed more orders in 2022 than they placed in 2021. Note, this
is the number of orders, not the value, and the particular field that we add the "count"
function to is not important (count is the same regardless of which field you count). We
chose the orderNumber in this case, but that choice is arbitrary
Customer.fetchData({
_constructor: "AdvancedCriteria", operator: "and", criteria: [
{fieldName: "country", operator: "equals", value: "USA"},
{
fieldQuery: {
dataSource: "Order",
summaryFunctions : { orderNumber : "count" },
criteria: {fieldName: "orderDate", operator: "iBetweenInclusive",
start:new Date("2021-01-01"), end:new Date("2021-12-31")}
},
operator: "lessThan",
valueQuery: {
dataSource: "Order",
summaryFunctions : { orderNumber : "count" },
criteria: {fieldName: "orderDate", operator: "iBetweenInclusive",
start:new Date("2022-01-01"), end:new Date("2022-12-31")}
}
}
]
});
- See Also:
-
Field Summary
Fields inherited from class com.smartgwt.client.core.RefDataClass
idFields inherited from class com.smartgwt.client.core.DataClass
factoryCreated, factoryProperties -
Constructor Summary
ConstructorsConstructorDescription -
Method Summary
Modifier and TypeMethodDescriptionIndicates whether this subquery can be implemented by embedding SQL directly in the wider SQL statement that will be used to resolve the fetch request.Optional criteria to use for this subquery.The name of theDataSourceto use for this subqueryOperation bindingto use for this subquery.static AdvancedCriterionSubquerygetOrCreateRef(JavaScriptObject jsObj) The default for a subquery is that the records are joined to the main DataSource on the firstforeignKeyone-to-many relationship found, in field order.The name of the field that will be used as the output of this query.setCanEmbedSQL(Boolean canEmbedSQL) Indicates whether this subquery can be implemented by embedding SQL directly in the wider SQL statement that will be used to resolve the fetch request.setCriteria(Criteria criteria) Optional criteria to use for this subquery.setDataSource(String dataSource) The name of theDataSourceto use for this subquerysetOperationId(String operationId) Operation bindingto use for this subquery.setQueryFK(String queryFK) The default for a subquery is that the records are joined to the main DataSource on the firstforeignKeyone-to-many relationship found, in field order.setQueryOutput(String queryOutput) The name of the field that will be used as the output of this query.Methods inherited from class com.smartgwt.client.data.DSRequest
getAdditionalOutputs, getArrayCriteriaForceExact, getComponentId, getDataProtocol, getEndRow, getExportAs, getExportCSS, getExportData, getExportDatesAsFormattedString, getExportDelimiter, getExportDisplay, getExportFields, getExportFilename, getExportFooter, getExportHeader, getExportHeaderless, getExportImageFormat, getExportImageQuality, getExportImageQualityAsDouble, getExportNumbersAsFormattedString, getExportPath, getExportPropertyIdentifier, getExportRawValues, getExportResults, getExportShowHeaderSpanTitles, getExportSpanTitleSeparator, getExportStreaming, getExportTitleSeparatorChar, getExportToClient, getExportToFilesystem, getExportTZ, getExportValueFields, getFieldValueExpressions, getGenerateRelatedUpdates, getGroupBy, getHeaderData, getKeepParentsOnFilter, getLineBreakStyle, getLinkDataFetchOperation, getOldValues, getOperationType, getOutputs, getParentNode, getPendingAdd, getProgressiveLoading, getRawSummaryFunctions, getRequestId, getResultSet, getResultTree, getShouldUseCache, getSortBy, getStartRow, getStreamResults, getSummaryFunctions, getTextMatchStyle, getUseFlatFields, getUseFlatHeaderFields, getUseStrictJSON, getValidationMode, setAdditionalOutputs, setArrayCriteriaForceExact, setAttribute, setCallback, setComponentId, setDataProtocol, setEndRow, setExportAs, setExportCSS, setExportData, setExportDatesAsFormattedString, setExportDelimiter, setExportDisplay, setExportFields, setExportFilename, setExportFooter, setExportHeader, setExportHeaderless, setExportImageFormat, setExportImageQuality, setExportImageQuality, setExportNumbersAsFormattedString, setExportPath, setExportPropertyIdentifier, setExportRawValues, setExportResults, setExportShowHeaderSpanTitles, setExportSpanTitleSeparator, setExportStreaming, setExportTitleSeparatorChar, setExportToClient, setExportToFilesystem, setExportTZ, setExportValueFields, setFieldValueExpressions, setGenerateRelatedUpdates, setGroupBy, setHeaderData, setKeepParentsOnFilter, setLineBreakStyle, setLinkDataFetchOperation, setOldValues, setOldValues, setOldValues, setOperationType, setOutputs, setParams, setPendingAdd, setProgressiveLoading, setRawSummaryFunctions, setShouldUseCache, setSkinName, setSortBy, setSortBy, setStartRow, setStreamResults, setSummaryFunctions, setTextMatchStyle, setUseFlatFields, setUseFlatHeaderFields, setUseStrictJSON, setValidationModeMethods inherited from class com.smartgwt.client.rpc.RPCRequest
downloadCallback, getActionURL, getAllowIE9Leak, getBypassCache, getCallbackParam, getContainsCredentials, getContentType, getData, getDataAsString, getDownloadResult, getDownloadToNewWindow, getEvalResult, getHttpHeaders, getHttpMethod, getHttpProxyURL, getIgnoreTimeout, getIsBackgroundRequest, getMockMode, getOmitNullMapValuesInResponse, getParams, getPrompt, getPromptCursor, getPromptDelay, getPromptStyle, getReportDownloadErrorsAsDocuments, getSendNoQueue, getServerOutputAsString, getShowPrompt, getSuppressAutoDraw, getTimeout, getTransport, getUseCursorTracker, getUseHttpProxy, getUseSimpleHttp, getWillHandleError, getWithCredentials, isDSRequest, setActionURL, setAllowIE9Leak, setBypassCache, setCallbackParam, setContainsCredentials, setContentType, setData, setData, setData, setData, setDownloadResult, setDownloadToNewWindow, setEvalResult, setEvalVars, setHttpHeaders, setHttpMethod, setHttpProxyURL, setIgnoreTimeout, setIsBackgroundRequest, setMockMode, setOmitNullMapValuesInResponse, setPrompt, setPromptCursor, setPromptDelay, setPromptStyle, setReportDownloadErrorsAsDocuments, setSendNoQueue, setServerOutputAsString, setShowPrompt, setSuppressAutoDraw, setTimeout, setTransport, setUseCursorTracker, setUseHttpProxy, setUseSimpleHttp, setWillHandleError, setWithCredentials, xhr_onProgressMethods inherited from class com.smartgwt.client.core.RefDataClass
getRef, getRef, internalSetIDMethods inherited from class com.smartgwt.client.core.DataClass
applyFactoryProperties, doAddHandler, fireEvent, getAttribute, getAttributeAsBoolean, getAttributeAsBoolean, getAttributeAsDate, getAttributeAsDouble, getAttributeAsDoubleArray, getAttributeAsElement, getAttributeAsFloat, getAttributeAsInt, getAttributeAsIntArray, getAttributeAsJavaScriptObject, getAttributeAsLong, getAttributeAsMap, getAttributeAsObject, getAttributeAsRecord, getAttributeAsString, getAttributeAsStringArray, getAttributes, getHandlerCount, isFactoryCreated, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttributeAsJavaObject, setFactoryCreated
-
Constructor Details
-
AdvancedCriterionSubquery
public AdvancedCriterionSubquery() -
AdvancedCriterionSubquery
-
-
Method Details
-
getOrCreateRef
-
setCanEmbedSQL
Indicates whether this subquery can be implemented by embedding SQL directly in the wider SQL statement that will be used to resolve the fetch request. This property is considered as part of a set of rules we apply to decide whether a subquery can be resolved by embedding SQL (which is the most efficient thing to do, and may be significantly faster), or if we must resolve by separating the subquery out into its ownDSRequestand manually applying the results.There are two reasons why we might decide to run a subquery as its own
DSRequest: First, if either the "main" dataSource or the subquery dataSource is not anSQL dataSource, then obviously we cannot merge into a single SQL statement. More subtly, if there is the possibility that customized logic might be in play, we run the subquery separately because in that case we may interfere with - or completely fail to apply - the custom logic if we do not run the subquery as a full-fledgedDSRequest.canEmbedSQLis intended to allow you to override our heuristics, for cases where you know a particular subquery definitely can, or definitely can't, be embedded.Note, whether or not we separate out the subquery into its own
DSRequest,declarative security rulesare always applied. So, for example, if the current user is not permitted to use thesubquery dataSourceor anoperationexplicitly named on the subquery, the entire fetch operation that the subquery is part of will fail. More nuanced, if the current user is prohibited byfield-level securityfrom viewing a field, that field will be stripped out of the subquery, which may lead to the subquery failing in a hard-to-predict way (but note, we always log a warning to the server logs when a field is removed in these circumstances).The rules around embedding or separating a subquery are, in order, as follows. As you can see,
canEmbedSQLoverrides all rules except the first (we obviously can't embed SQL if one of the dataSources isn't implemented using SQL)- If either the "main" dataSource or the subquery dataSource is not an
sql dataSource, the subquery must by separated. Otherwise, - If the
canEmbedSQLflag is non-null, we honor it. Otherwise, - If the subquery specifies an explicit operationId, the subquery must be separated. Otherwise,
- If the subquery dataSource
declares a custom fetch
operation(that is, a fetch operation that does not declare anoperationId), the subquery must be separated. Otherwise, - If the subquery dataSource declares either of the dataSource-level customization
properties
DataSource.serverObjectorDataSource.script, the subquery must be separated. Otherwise, - If the subquery DataSource is a direct instance of the base class (ie, its canonical class name is
com.isomorphic.sql.SQLDataSource), the subquery can be embedded. Otherwise, - We now know that
subquery dataSource is a subclass of
SQLDataSource. We use Reflection to inspect the implementing class: if it overrides any of the methodsexecute(),executeFetch{}orSQLExecute, the subquery must be separated (note, we cache the results of these tests so Reflection is only used the first time a given dataSource instance is used) - If we get to this point without having decided whether the subquery can be embedded, or must be separated, the subquery can be embedded
- Parameters:
canEmbedSQL- New canEmbedSQL value. Default value is null- Returns:
AdvancedCriterionSubqueryinstance, for chaining setter calls- See Also:
- If either the "main" dataSource or the subquery dataSource is not an
-
getCanEmbedSQL
Indicates whether this subquery can be implemented by embedding SQL directly in the wider SQL statement that will be used to resolve the fetch request. This property is considered as part of a set of rules we apply to decide whether a subquery can be resolved by embedding SQL (which is the most efficient thing to do, and may be significantly faster), or if we must resolve by separating the subquery out into its ownDSRequestand manually applying the results.There are two reasons why we might decide to run a subquery as its own
DSRequest: First, if either the "main" dataSource or the subquery dataSource is not anSQL dataSource, then obviously we cannot merge into a single SQL statement. More subtly, if there is the possibility that customized logic might be in play, we run the subquery separately because in that case we may interfere with - or completely fail to apply - the custom logic if we do not run the subquery as a full-fledgedDSRequest.canEmbedSQLis intended to allow you to override our heuristics, for cases where you know a particular subquery definitely can, or definitely can't, be embedded.Note, whether or not we separate out the subquery into its own
DSRequest,declarative security rulesare always applied. So, for example, if the current user is not permitted to use thesubquery dataSourceor anoperationexplicitly named on the subquery, the entire fetch operation that the subquery is part of will fail. More nuanced, if the current user is prohibited byfield-level securityfrom viewing a field, that field will be stripped out of the subquery, which may lead to the subquery failing in a hard-to-predict way (but note, we always log a warning to the server logs when a field is removed in these circumstances).The rules around embedding or separating a subquery are, in order, as follows. As you can see,
canEmbedSQLoverrides all rules except the first (we obviously can't embed SQL if one of the dataSources isn't implemented using SQL)- If either the "main" dataSource or the subquery dataSource is not an
sql dataSource, the subquery must by separated. Otherwise, - If the
canEmbedSQLflag is non-null, we honor it. Otherwise, - If the subquery specifies an explicit operationId, the subquery must be separated. Otherwise,
- If the subquery dataSource
declares a custom fetch
operation(that is, a fetch operation that does not declare anoperationId), the subquery must be separated. Otherwise, - If the subquery dataSource declares either of the dataSource-level customization
properties
DataSource.serverObjectorDataSource.script, the subquery must be separated. Otherwise, - If the subquery DataSource is a direct instance of the base class (ie, its canonical class name is
com.isomorphic.sql.SQLDataSource), the subquery can be embedded. Otherwise, - We now know that
subquery dataSource is a subclass of
SQLDataSource. We use Reflection to inspect the implementing class: if it overrides any of the methodsexecute(),executeFetch{}orSQLExecute, the subquery must be separated (note, we cache the results of these tests so Reflection is only used the first time a given dataSource instance is used) - If we get to this point without having decided whether the subquery can be embedded, or must be separated, the subquery can be embedded
- Returns:
- Current canEmbedSQL value. Default value is null
- See Also:
- If either the "main" dataSource or the subquery dataSource is not an
-
setCriteria
Optional criteria to use for this subquery. Note, subqueries usually have implicit criteria, because they are joined to the main dataSource fetch unless thequeryFKis set to the special value "*none*".Also, because subqueries are themselves part of a larger set of criteria, the subquery result is compared to some other value in that larger criteria - it is easy to get confused by this multi-level criteria issue. You may find it helpful to think of this property as "inside criteria" (criteria used inside this subquery to derive its result) and the criterion of which the subquery is a component (as a
fieldQueryorvalueQuery), as "outside criteria"- Overrides:
setCriteriain classDSRequest- Parameters:
criteria- New criteria value. Default value is null- Returns:
AdvancedCriterionSubqueryinstance, for chaining setter calls- See Also:
-
getCriteria
Optional criteria to use for this subquery. Note, subqueries usually have implicit criteria, because they are joined to the main dataSource fetch unless thequeryFKis set to the special value "*none*".Also, because subqueries are themselves part of a larger set of criteria, the subquery result is compared to some other value in that larger criteria - it is easy to get confused by this multi-level criteria issue. You may find it helpful to think of this property as "inside criteria" (criteria used inside this subquery to derive its result) and the criterion of which the subquery is a component (as a
fieldQueryorvalueQuery), as "outside criteria"- Overrides:
getCriteriain classDSRequest- Returns:
- Current criteria value. Default value is null
- See Also:
-
setDataSource
The name of theDataSourceto use for this subquery- Overrides:
setDataSourcein classDSRequest- Parameters:
dataSource- New dataSource value. Default value is null- Returns:
AdvancedCriterionSubqueryinstance, for chaining setter calls- See Also:
-
getDataSource
The name of theDataSourceto use for this subquery- Overrides:
getDataSourcein classDSRequest- Returns:
- Current dataSource value. Default value is null
- See Also:
-
setOperationId
Operation bindingto use for this subquery. Note, this refers to anoperationBindingon thesubquery dataSource, not the DataSource associated with the overall fetch request. Also note that specifying anoperationIdwill cause Smart GWT to run the subquery separately by default, which may have performance implications. This default behavior can be overridden - seecanEmbedSQLfor details.- Overrides:
setOperationIdin classDSRequest- Parameters:
operationId- New operationId value. Default value is null- Returns:
AdvancedCriterionSubqueryinstance, for chaining setter calls- See Also:
-
getOperationId
Operation bindingto use for this subquery. Note, this refers to anoperationBindingon thesubquery dataSource, not the DataSource associated with the overall fetch request. Also note that specifying anoperationIdwill cause Smart GWT to run the subquery separately by default, which may have performance implications. This default behavior can be overridden - seecanEmbedSQLfor details.- Overrides:
getOperationIdin classDSRequest- Returns:
- Current operationId value. Default value is null
- See Also:
-
setQueryFK
The default for a subquery is that the records are joined to the main DataSource on the firstforeignKeyone-to-many relationship found, in field order. So for example, queryingCustomers with a subquery onOrders, we discoverOrder.customerIdFK pointing toCustomer.id. More complicated relations are also auto-discovered: for example, queryingCustomers with a subquery onOrderLines, we will discover the link toCustomerviaOrderLine.orderNumberand thenOrder.customerId.For many use cases, there is only one relation between any two DataSources, so this default discovery of the relation is often sufficient. However, if you need to, you can optionally specify a
queryFKas the fieldName of aforeignKeyfrom the "many" to the "one". If the relation is indirect - as with the join fromOrderLinetoCustomerdescribed above - you can specifyqueryFKas a dot-separated path from "many" to "one", like this:queryFK: "orderNumber.customerId"(but note that this is optional - often, a start point is all that is required to identify the relation-path to use)NOTE:The
queryFKproperty leverages theincludeViafeature, and so is constrained by the same restrictions as that feature. Primarily, this means thatqueryFKcan only name aforeignKeyfield on thesubquery dataSouce; it is not valid to name a field on the main dataSource. In practice, this is not usually a restriction because typically the subquery dataSource will be at the "many" end of a direct or indirect relation to the main dataSource, and so is naturally the one that declares theforeignKeyYou can also specify the special value "*none*" for
queryFK, which means the aggregation query should be done independently from the main query, to simply produce a value separately without any joins to the main dataset. A subquery that specifiesqueryFK: "*none*"is quite unusual because most use cases of subqueries require a join to the parent dataSource; however, valid use cases do exist - see the "Simple valueQuery" example on thesubquery overview page- Parameters:
queryFK- New queryFK value. Default value is null- Returns:
AdvancedCriterionSubqueryinstance, for chaining setter calls- See Also:
-
getQueryFK
The default for a subquery is that the records are joined to the main DataSource on the firstforeignKeyone-to-many relationship found, in field order. So for example, queryingCustomers with a subquery onOrders, we discoverOrder.customerIdFK pointing toCustomer.id. More complicated relations are also auto-discovered: for example, queryingCustomers with a subquery onOrderLines, we will discover the link toCustomerviaOrderLine.orderNumberand thenOrder.customerId.For many use cases, there is only one relation between any two DataSources, so this default discovery of the relation is often sufficient. However, if you need to, you can optionally specify a
queryFKas the fieldName of aforeignKeyfrom the "many" to the "one". If the relation is indirect - as with the join fromOrderLinetoCustomerdescribed above - you can specifyqueryFKas a dot-separated path from "many" to "one", like this:queryFK: "orderNumber.customerId"(but note that this is optional - often, a start point is all that is required to identify the relation-path to use)NOTE:The
queryFKproperty leverages theincludeViafeature, and so is constrained by the same restrictions as that feature. Primarily, this means thatqueryFKcan only name aforeignKeyfield on thesubquery dataSouce; it is not valid to name a field on the main dataSource. In practice, this is not usually a restriction because typically the subquery dataSource will be at the "many" end of a direct or indirect relation to the main dataSource, and so is naturally the one that declares theforeignKeyYou can also specify the special value "*none*" for
queryFK, which means the aggregation query should be done independently from the main query, to simply produce a value separately without any joins to the main dataset. A subquery that specifiesqueryFK: "*none*"is quite unusual because most use cases of subqueries require a join to the parent dataSource; however, valid use cases do exist - see the "Simple valueQuery" example on thesubquery overview page- Returns:
- Current queryFK value. Default value is null
- See Also:
-
setQueryOutput
The name of the field that will be used as the output of this query. Only useful if your subquery returns more than one field, and optional even in that case. See theSubqueries overviewfor more details- Parameters:
queryOutput- New queryOutput value. Default value is null- Returns:
AdvancedCriterionSubqueryinstance, for chaining setter calls- See Also:
-
getQueryOutput
The name of the field that will be used as the output of this query. Only useful if your subquery returns more than one field, and optional even in that case. See theSubqueries overviewfor more details- Returns:
- Current queryOutput value. Default value is null
- See Also:
-