Queries
Last updated
Last updated
A FlowScript sequence value represents an ordered list of elements. This document describes how to write query expressions to filter, order, group, join and modify such sequences.
Remember that all values in FlowScript are immutable. You cannot change a sequence value; you can only make modified copies of it.
To filter a sequence of records, use the where operator. This operator takes a sequence expression on the left and a filter expression on the right. The resulting values contains only the records for which the filter expression evaluates to true.
As demonstrated in the example above, the filter expression has access to each member in the sequence's records as if they were local variables. The expression active == 1, denoting a boolean value indicating whether a user's "active" flag is equal to one, is written from a perspective "inside" a record.
It is also possible to use the where operator with an .
To order a sequence of records, use the order by operator, which takes a sequence expression on the left and a comma-separated list of sort specifiers on the right. In the example below, the countries are sorted by population, descending order, and secondarily by name in ascending order (making sure the Netherlands and Zambia, having the same population size in this example, come in alphabetical order).
FlowScript supports an SQL-like query syntax for sequences of records. The example below queries a sequence of countries, transforming the populationInMillions field of each record into a member labelled "population", ordering the result by the new population member in ascending order.
Select queries can select, filter, group, join and sort records using the select, where, group by, join and order by clauses. Only the select clause is mandatory.
The select clause specifies the format of the query result. A select query starts with the keyword select followed by a comma-separated list of expressions giving the members to include, the from keyword, and a source expression. If the wildcard (*) symbol is included in the list of member expressions, all members of the source table are included:
A member expression may be implicitly or explicitly labelled. Complex expressions (including more than one identifier) must be explicitly labelled. Explicitly labelled members are declared using the as keyword. In the following example, the "name" member is implicitly labelled and will have the label "name" in the resulting sequence of records. The second member is explicitly labelled "population". Because there is no wildcard symbol, the populationInMillions member will not be a part of the result.
If the select keyword is followed by the distinct keyword, only distinct records are included in the result:
The group by clause is used to group rows that share some values into summary rows, typically in combination with aggregation functions like sum, count, etc.
The following example takes a list of sales transactions and groups them by the sold product, summing the quantity and price for each product. It also includes the customerID members without any grouping.
Join clauses are used to combine records from two sequences based one some relationship between the records. In the example below, each sales transaction is paired with the name of the corresponding customer. The last transaction (with ID 6) has no curresponding customer, so its customer name will be null.
Left join will return all elements from the left sequence and all matching records in the right sequence. Where no matching element is found on the right, fields selected from the right will be null
.
A mirror image of the left join, right join will return all elements from the right sequence and all matching records in the left sequence. Where no matching element is found on the left, fields selected from the left will be null
.
Inner join will return all of the matching pair of elements from both of the sequences.
Outer join will return all elements from both of the sequences in the select join clause, adding null on all fields for non-matching elements.
All the different query types support aliases, which is useful if the records in the queries sequence contain some member whose label is the same as the name of some variable.
The different types of query syntax described above are well suited for table-like sequences of records. It is less well suited for nested structures, sequences of simple values or sequences of sequences. For these cases, you can use functional-style queries using functions defined in the Seq module.
In the example below, each customer record contains its own list of transactions. A functional-style query is used to find the sum of the total price of all transactions for all customers.
The where clause filters the result set, much like the standalone keyword: