Using joins in stream queries
There are two types of joins that can be used within a stream query: cross-joins and equi-joins.
A cross-join of two sets combines every item from one set with each item from the other set. A cross-join is performed by using two, top-level from clauses in a query. We have already seen an example of this:
01. TemperatureAndPressure tp;
02. stream<Temperature> temperatures := all Temperature(sensorId="T001");
03. stream<Pressure> pressures := all Pressure(sensorId="P001");
04. stream<float> meanTs := from t in temperature retain 3 select mean(t.temperature);
05. stream<float> meanPs := from p in pressure retain 3 select mean(p.pressure);
06. from t in meanTs retain 1
07. from p in meanPs retain 1
08. select TemperatureAndPressure("S001",t,p) : tp {
09. print tp.toString();
10. }
An equi-join is performed by following the initial from clause with a join clause. An equi-join of two sets combines items in the two sets where a specified key value of the item in the first set matches a specified key value of the item in the second set. Separate key value expressions for each source item identify the key values to be compared. For example:
01. TemperatureAndPressure tp;
02. from t in all Temperature() partition by t.sensorId retain 1
03. join p in all Pressure() partition by p.sensorId retain 1
04 on sensorNumber(t.sensorId) equals sensorNumber(p.sensorId)
05. select TemperatureAndPressure(combinedId(t.sensorId), t.temperature, p.pressure) : tp {
06. print tp.toString();
07. }
When considering performance, cross-joins will in general be less efficient than equi-joins. It is advised that cross-joins only be used where the number of items in the stream windows is small, as in the example at the beginning of this topic.
Note that joins can be performed between a stream10 and a window. For example:
01. TemperatureAndPressure tp;
02. stream<Temperature> temperatures := all Temperature(sensorId="T001"); 1
03. stream<Pressure> pressures := all Pressure(sensorId="P001");
04. from t in temperatures from p in pressures retain 1
05. select TemperatureAndPressure ("S001",t.temperature,p.pressure) : tp {
06. print tp.toString();
07. }
This join will produce an output item whenever there is a new Temperature event for the sensor but not when there is a new Pressure event. The temperature and pressure events arrive at different times; when the temperature event arrives, because of the retain 1 in the right side from clause, there is a pressure event available for joining with; but, because there is no window operation in the left side from clause, when a pressure event arrives, there is no temperature event to join with.
10 That is, where no window operators are applied to the stream, in the query.