<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://training-course-material.com/index.php?action=history&amp;feed=atom&amp;title=MVEL_advanced</id>
	<title>MVEL advanced - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://training-course-material.com/index.php?action=history&amp;feed=atom&amp;title=MVEL_advanced"/>
	<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=MVEL_advanced&amp;action=history"/>
	<updated>2026-05-13T23:42:15Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://training-course-material.com/index.php?title=MVEL_advanced&amp;diff=75264&amp;oldid=prev</id>
		<title>Fstachecki: /* Accumulate Functions ⌘ */</title>
		<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=MVEL_advanced&amp;diff=75264&amp;oldid=prev"/>
		<updated>2019-12-16T20:29:49Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Accumulate Functions ⌘&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Cat|Drools Filip|060}}&lt;br /&gt;
&lt;br /&gt;
== Drools Expert - mvel - RHS - advanced Training Materials ==&lt;br /&gt;
{{Can I use your material}}&lt;br /&gt;
&lt;br /&gt;
== Selecting data from many different Fact Types ⌘==&lt;br /&gt;
&lt;br /&gt;
Cartesian product (direct product) &lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    d :Dept()&lt;br /&gt;
    e :Emp()&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot;\t&amp;quot; + d.dname)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 ELISON	OPERATIONS&lt;br /&gt;
 ELISON	SALES&lt;br /&gt;
 ELISON	RESEARCH&lt;br /&gt;
 ELISON	ACCOUNTING&lt;br /&gt;
 FORD	OPERATIONS&lt;br /&gt;
 FORD	SALES&lt;br /&gt;
 FORD	RESEARCH&lt;br /&gt;
 FORD	ACCOUNTING&lt;br /&gt;
 ...&lt;br /&gt;
 BUSH	OPERATIONS&lt;br /&gt;
 BUSH	SALES&lt;br /&gt;
 BUSH	RESEARCH&lt;br /&gt;
 BUSH	ACCOUNTING&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Only those pairs which have the matching deptno in both fact types should be selected&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
   d :Dept()&lt;br /&gt;
   e :Emp(d.deptno == deptno)&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot;\t&amp;quot; + d.dname)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 ELISON	ACCOUNTING&lt;br /&gt;
 FORD	RESEARCH&lt;br /&gt;
 CARNEGIE	RESEARCH&lt;br /&gt;
 THATCHER	RESEARCH&lt;br /&gt;
 TOOSK	RESEARCH&lt;br /&gt;
 WALTON	SALES&lt;br /&gt;
 BUFFETT	SALES&lt;br /&gt;
 GATES	SALES&lt;br /&gt;
 BAROSSO	SALES&lt;br /&gt;
 CHIRACK	SALES&lt;br /&gt;
 PUTIN	RESEARCH&lt;br /&gt;
 MERKEL	ACCOUNTING&lt;br /&gt;
 BLAIR	SALES&lt;br /&gt;
 BUSH	ACCOUNTING&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Salgrade Example&lt;br /&gt;
Find the name of an employee and their salary grade&lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    s :Salgrade()&lt;br /&gt;
    e :Emp(sal &amp;gt;= s.losal &amp;amp;&amp;amp; &amp;lt;= s.hisal)&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot;\t&amp;quot; + s.grade)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ELISON	2&lt;br /&gt;
 FORD	1&lt;br /&gt;
 CARNEGIE	4&lt;br /&gt;
 THATCHER	1&lt;br /&gt;
 TOOSK	4&lt;br /&gt;
 WALTON	2&lt;br /&gt;
 BUFFETT	1&lt;br /&gt;
 GATES	3&lt;br /&gt;
 BAROSSO	3&lt;br /&gt;
 CHIRACK	2&lt;br /&gt;
 PUTIN	4&lt;br /&gt;
 MERKEL	4&lt;br /&gt;
 BLAIR	4&lt;br /&gt;
 BUSH	5&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;More Complex Example ⌘&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    s :Salgrade()&lt;br /&gt;
    d :Dept()&lt;br /&gt;
    e :Emp(sal &amp;gt;= s.losal &amp;amp;&amp;amp; &amp;lt;= s.hisal, d.deptno == deptno)&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot;\t&amp;quot; + s.grade + &amp;quot;\t&amp;quot; + d.dname )&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 ELISON	2	ACCOUNTING&lt;br /&gt;
 FORD	1	RESEARCH&lt;br /&gt;
 CARNEGIE	4	RESEARCH&lt;br /&gt;
 THATCHER	1	RESEARCH&lt;br /&gt;
 TOOSK	4	RESEARCH&lt;br /&gt;
 WALTON	2	SALES&lt;br /&gt;
 BUFFETT	1	SALES&lt;br /&gt;
 GATES	3	SALES&lt;br /&gt;
 BAROSSO	3	SALES&lt;br /&gt;
 CHIRACK	2	SALES&lt;br /&gt;
 PUTIN	4	RESEARCH&lt;br /&gt;
 MERKEL	4	ACCOUNTING&lt;br /&gt;
 BLAIR	4	SALES&lt;br /&gt;
 BUSH	5	ACCOUNTING&lt;br /&gt;
&lt;br /&gt;
===Exercises===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;31.  Exercise&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select the name of the employee and the city (LOC column in DEPT table) in which they work.&lt;br /&gt;
&lt;br /&gt;
  BUSH      NEW YORK &lt;br /&gt;
  BLAIR     PARIS    &lt;br /&gt;
  MERKEL    NEW YORK &lt;br /&gt;
  PUTIN     LONDON   &lt;br /&gt;
  CHIRACK   PARIS    &lt;br /&gt;
  BAROSSO   PARIS    &lt;br /&gt;
  GATES     PARIS    &lt;br /&gt;
  BUFFETT   PARIS    &lt;br /&gt;
  WALTON    PARIS    &lt;br /&gt;
  TOOSK     LONDON   &lt;br /&gt;
  THATCHER  LONDON   &lt;br /&gt;
  CARNEGIE  LONDON   &lt;br /&gt;
  FORD      LONDON   &lt;br /&gt;
  ELISON    NEW YORK &lt;br /&gt;
 &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;32.  Exercise&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select the names of the employees, and the name and number of their department.&lt;br /&gt;
&lt;br /&gt;
  BUSH      ACCOUNTING  10     &lt;br /&gt;
  BLAIR     SALES       30     &lt;br /&gt;
  MERKEL    ACCOUNTING  10     &lt;br /&gt;
  PUTIN     RESEARCH    20     &lt;br /&gt;
  CHIRACK   SALES       30     &lt;br /&gt;
  BAROSSO   SALES       30     &lt;br /&gt;
  GATES     SALES       30     &lt;br /&gt;
  BUFFETT   SALES       30     &lt;br /&gt;
  WALTON    SALES       30     &lt;br /&gt;
  TOOSK     RESEARCH    20     &lt;br /&gt;
  THATCHER  RESEARCH    20     &lt;br /&gt;
  CARNEGIE  RESEARCH    20     &lt;br /&gt;
  FORD      RESEARCH    20     &lt;br /&gt;
  ELISON    ACCOUNTING  10     &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;33.  Exercise&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select the names of the employees, their salary and salary grade, but only those whose salary is more than 2000.&lt;br /&gt;
&lt;br /&gt;
  BUSH      5000.00  5     &lt;br /&gt;
  BLAIR     2850.00  4     &lt;br /&gt;
  MERKEL    2450.00  4     &lt;br /&gt;
  PUTIN     2975.00  4     &lt;br /&gt;
  TOOSK     3000.00  4     &lt;br /&gt;
  CARNEGIE  3000.00  4     &lt;br /&gt;
 &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;34.  Exercise&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select employees working in London.&lt;br /&gt;
&lt;br /&gt;
  PUTIN     LONDON &lt;br /&gt;
  TOOSK     LONDON &lt;br /&gt;
  THATCHER  LONDON &lt;br /&gt;
  CARNEGIE  LONDON &lt;br /&gt;
  FORD      LONDON &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;35.  Exercise&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select employees and their salary grades except those from London.&lt;br /&gt;
&lt;br /&gt;
  BUSH     NEW YORK  5     &lt;br /&gt;
  BLAIR    PARIS     4     &lt;br /&gt;
  MERKEL   NEW YORK  4     &lt;br /&gt;
  CHIRACK  PARIS     2     &lt;br /&gt;
  BAROSSO  PARIS     3     &lt;br /&gt;
  GATES    PARIS     3     &lt;br /&gt;
  BUFFETT  PARIS     1     &lt;br /&gt;
  WALTON   PARIS     2     &lt;br /&gt;
  ELISON   NEW YORK  2&lt;br /&gt;
&lt;br /&gt;
== Finding outstanding facts ⌘==&lt;br /&gt;
Find departments with employees&lt;br /&gt;
 when&lt;br /&gt;
    d :Dept()&lt;br /&gt;
    exists (Emp(deptno == d.deptno))&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println( d.dname )&lt;br /&gt;
&lt;br /&gt;
 ACCOUNTING&lt;br /&gt;
 RESEARCH&lt;br /&gt;
 SALES&lt;br /&gt;
&lt;br /&gt;
Find departments without employees&lt;br /&gt;
 when&lt;br /&gt;
    d :Dept()&lt;br /&gt;
    not (Emp(deptno == d.deptno))&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println( d.dname )&lt;br /&gt;
&lt;br /&gt;
 OPERATIONS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Looking up Facts of the same type&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We need to report who is whose boss&lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    e :Emp()&lt;br /&gt;
    m :Emp(id == e.mgr)&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println( e.name + &amp;quot; reports to &amp;quot; + m.name )&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 ELISON reports to MERKEL&lt;br /&gt;
 FORD reports to CARNEGIE&lt;br /&gt;
 CARNEGIE reports to PUTIN&lt;br /&gt;
 THATCHER reports to TOOSK&lt;br /&gt;
 TOOSK reports to PUTIN&lt;br /&gt;
 WALTON reports to BLAIR&lt;br /&gt;
 BUFFETT reports to BLAIR&lt;br /&gt;
 GATES reports to BLAIR&lt;br /&gt;
 BAROSSO reports to BLAIR&lt;br /&gt;
 CHIRACK reports to BLAIR&lt;br /&gt;
 PUTIN reports to BUSH&lt;br /&gt;
 MERKEL reports to BUSH&lt;br /&gt;
 BLAIR reports to BUSH&lt;br /&gt;
&lt;br /&gt;
==Exercises==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;36.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find departments without employees.&lt;br /&gt;
&lt;br /&gt;
 OPERATIONS&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;37.  *Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select an employee’s name and his/her boss’s name&lt;br /&gt;
&lt;br /&gt;
 ELISON boss is MERKEL&lt;br /&gt;
 FORD boss is CARNEGIE&lt;br /&gt;
 CARNEGIE boss is PUTIN&lt;br /&gt;
 THATCHER boss is TOOSK&lt;br /&gt;
 TOOSK boss is PUTIN&lt;br /&gt;
 WALTON boss is BLAIR&lt;br /&gt;
 BUFFETT boss is BLAIR&lt;br /&gt;
 GATES boss is BLAIR&lt;br /&gt;
 BAROSSO boss is BLAIR&lt;br /&gt;
 CHIRACK boss is BLAIR&lt;br /&gt;
 PUTIN boss is BUSH&lt;br /&gt;
 MERKEL boss is BUSH&lt;br /&gt;
 BLAIR boss is BUSH&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;38.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select an employee who doesn&amp;#039;t have a boss.&lt;br /&gt;
&lt;br /&gt;
 BUSH&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;39.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Show all employees who have no subordinates.&lt;br /&gt;
&lt;br /&gt;
 ELISON&lt;br /&gt;
 FORD&lt;br /&gt;
 THATCHER&lt;br /&gt;
 WALTON&lt;br /&gt;
 BUFFETT&lt;br /&gt;
 GATES&lt;br /&gt;
 BAROSSO&lt;br /&gt;
 CHIRACK&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;41.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select employees hired earlier than their bosses.&lt;br /&gt;
&lt;br /&gt;
  THATCHER was hired in 1980, her boss TOOSK who was hired in 1981&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;44.  ***Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find jobs which are in department 10 but not in department 20.&lt;br /&gt;
&lt;br /&gt;
 PRESIDENT&lt;br /&gt;
&lt;br /&gt;
== Accumulate Functions ⌘==&lt;br /&gt;
&lt;br /&gt;
Drools has a couple of built in &amp;#039;&amp;#039;&amp;#039;accumulate&amp;#039;&amp;#039;&amp;#039; functions:&lt;br /&gt;
* average&lt;br /&gt;
* min&lt;br /&gt;
* max&lt;br /&gt;
* count&lt;br /&gt;
* sum&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* collectList&lt;br /&gt;
* collectSet&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Find the average salary in the whole company.&lt;br /&gt;
&lt;br /&gt;
 when&lt;br /&gt;
    avg: Number() from accumulate (Emp(s: sal),average(s))&lt;br /&gt;
 then    &lt;br /&gt;
    System.out.println(avg)&lt;br /&gt;
&lt;br /&gt;
 2073&lt;br /&gt;
&lt;br /&gt;
Which can be also written this way:&lt;br /&gt;
 when&lt;br /&gt;
   accumulate (e: Emp(), avg : average(e.sal)) &lt;br /&gt;
 then    &lt;br /&gt;
 System.out.println(avg)&lt;br /&gt;
&lt;br /&gt;
Syntax&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
accumulate( &amp;lt;source pattern&amp;gt;; &amp;lt;functions&amp;gt; [;&amp;lt;constraints&amp;gt;] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comparing to SQL:&lt;br /&gt;
 SELECT AVG(column-name)&lt;br /&gt;
  FROM table-name&lt;br /&gt;
&lt;br /&gt;
You can also use many accumulate functions in one go:&lt;br /&gt;
 when&lt;br /&gt;
   accumulate (e: Emp(), &lt;br /&gt;
   	$avg : average(e.sal),&lt;br /&gt;
   	$min : min(e.sal),&lt;br /&gt;
   	$max : max(e.sal)&lt;br /&gt;
   	) &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(&lt;br /&gt;
    &amp;quot;Average salary: &amp;quot; + $avg + &amp;quot;\n&amp;quot; +&lt;br /&gt;
   &amp;quot;Min salary: &amp;quot; + $min + &amp;quot;\n&amp;quot; +&lt;br /&gt;
   &amp;quot;Max salary: &amp;quot; + $max + &amp;quot;\n&amp;quot;&lt;br /&gt;
   )&lt;br /&gt;
&lt;br /&gt;
 Average salary: 2073.214285714286&lt;br /&gt;
 Min salary: 800.0&lt;br /&gt;
 Max salary: 5000.0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Exercises ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;23.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find the minimal, maximal and average salaries of people employed in 1981.&lt;br /&gt;
&lt;br /&gt;
 Average salary: 2282.5&lt;br /&gt;
 Min salary: 950.0&lt;br /&gt;
 Max salary: 5000.0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;24.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find the difference between maximal and minimal salary.&lt;br /&gt;
&lt;br /&gt;
 Salary range: 4200.0&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;26.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
How many managers work for the company?&lt;br /&gt;
&lt;br /&gt;
 3&lt;br /&gt;
&lt;br /&gt;
== Groups ⌘==&lt;br /&gt;
&lt;br /&gt;
Groups contain all facts which have the same values in a property or properties&lt;br /&gt;
&lt;br /&gt;
Also known as factor levels in statistics.&lt;br /&gt;
&lt;br /&gt;
  CARNEGIE  ANALYST    3000.00 &lt;br /&gt;
  TOOSK     ANALYST    3000.00 &lt;br /&gt;
  ELISON    CLERK      1300.00 &lt;br /&gt;
  FORD      CLERK      1100.00 &lt;br /&gt;
  THATCHER  CLERK      800.00  &lt;br /&gt;
  BUFFETT   CLERK      950.00  &lt;br /&gt;
  PUTIN     MANAGER    2975.00 &lt;br /&gt;
  MERKEL    MANAGER    2450.00 &lt;br /&gt;
  BLAIR     MANAGER    2850.00 &lt;br /&gt;
  BUSH      PRESIDENT  5000.00 &lt;br /&gt;
  GATES     SALESMAN   1500.00 &lt;br /&gt;
  BAROSSO   SALESMAN   1600.00 &lt;br /&gt;
  WALTON    SALESMAN   1250.00 &lt;br /&gt;
  CHIRACK   SALESMAN   1250.00 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are five JOB groups above: ANALYST, CLERK, MANAGER, PRESIDENT and SALESMAN.&lt;br /&gt;
&lt;br /&gt;
Comparing to SQL:&lt;br /&gt;
&lt;br /&gt;
 SELECT job, avg(sal)&lt;br /&gt;
 FROM Emp &lt;br /&gt;
 GROUP BY job;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Example&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
   Emp(j: job) &lt;br /&gt;
   accumulate (e :Emp(job == j),    	$avg : average(e.sal)  	) &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(   &amp;quot;Average salary in position &amp;quot; + j + &amp;quot;is: &amp;quot; + $avg ) &lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 Average salary in position CLERKis: 1037.5&lt;br /&gt;
 Average salary in position CLERKis: 1037.5&lt;br /&gt;
 Average salary in position ANALYSTis: 3000.0&lt;br /&gt;
 Average salary in position CLERKis: 1037.5&lt;br /&gt;
 Average salary in position ANALYSTis: 3000.0&lt;br /&gt;
 Average salary in position SALESMANis: 1400.0&lt;br /&gt;
 Average salary in position CLERKis: 1037.5&lt;br /&gt;
 Average salary in position SALESMANis: 1400.0&lt;br /&gt;
 Average salary in position SALESMANis: 1400.0&lt;br /&gt;
 Average salary in position SALESMANis: 1400.0&lt;br /&gt;
 Average salary in position MANAGERis: 2758.3333333333335&lt;br /&gt;
 Average salary in position MANAGERis: 2758.3333333333335&lt;br /&gt;
 Average salary in position MANAGERis: 2758.3333333333335&lt;br /&gt;
 Average salary in position PRESIDENTis: 5000.0&lt;br /&gt;
&lt;br /&gt;
=== Declaring and inserting new facts ⌘===&lt;br /&gt;
The problem with the solution above is that it repeats (loops) 14 times (the number of employees).&lt;br /&gt;
&lt;br /&gt;
To solve this problem, we need to mark a group by inserting new fact SalByJob, and check whether we have already calculated the average, which the condition &lt;br /&gt;
 not SalByJob(j == job)&lt;br /&gt;
does.&lt;br /&gt;
&lt;br /&gt;
The code below will return exactly 5 averages.&lt;br /&gt;
&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;declare SalByJob&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;job : String&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;avgSal : Double&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;end&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 &lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    Emp(j: job) and&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;not SalByJob(j == job)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    accumulate (e :Emp(job == j), 	$avg : average(e.sal)   	) &lt;br /&gt;
 then    &lt;br /&gt;
    System.out.println(   &amp;quot;Average salary in position &amp;quot; + j + &amp;quot;is: &amp;quot; + $avg + &amp;quot;\n&amp;quot; )&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;insert(new SalByJob(j,$avg))&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Simpler version:&lt;br /&gt;
&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;declare SalByJob&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;job : String&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;end&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 &lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    Emp(j: job) and&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;not SalByJob(j == job)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    accumulate (e :Emp(job == j), 	$avg : average(e.sal)   	) &lt;br /&gt;
 then    &lt;br /&gt;
    System.out.println(   &amp;quot;Average salary in position &amp;quot; + j + &amp;quot;is: &amp;quot; + $avg )&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;insert(new SalByJob(j))&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 Average salary in position CLERKis: 1037.5&lt;br /&gt;
 Average salary in position ANALYSTis: 3000.0&lt;br /&gt;
 Average salary in position SALESMANis: 1400.0&lt;br /&gt;
 Average salary in position MANAGERis: 2758.3333333333335&lt;br /&gt;
 Average salary in position PRESIDENTis: 5000.0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Another Example&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Let’s find out how many people were hired in a specific year&lt;br /&gt;
&lt;br /&gt;
 declare PeopleHiredInYear&lt;br /&gt;
    year : int&lt;br /&gt;
    pplcnt : int&lt;br /&gt;
 end&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
    Emp(y: hiredate) and  not PeopleHiredInYear(y == year)&lt;br /&gt;
    accumulate (e :Emp(hiredate == y), $pplcnt : count(e.id)) &lt;br /&gt;
 then    &lt;br /&gt;
    System.out.println(  &amp;quot;In &amp;quot; + y + &amp;quot; there where &amp;quot; + $pplcnt + &amp;quot; people hired&amp;quot;) &lt;br /&gt;
    insert(new PeopleHiredInYear(y,$pplcnt))&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 In 1982 there where 2 people hired &lt;br /&gt;
 In 1983 there where 1 people hired &lt;br /&gt;
 In 1980 there where 1 people hired &lt;br /&gt;
 In 1981 there where 10 people hired&lt;br /&gt;
&lt;br /&gt;
Simpler version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
declare PeopleHiredInYear&lt;br /&gt;
   year : int&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
when&lt;br /&gt;
   Emp($y: hiredate) and  &lt;br /&gt;
   not PeopleHiredInYear($y == year)&lt;br /&gt;
   accumulate ($e :Emp(hiredate == $y), $pplcnt : count($e.id)) &lt;br /&gt;
then    &lt;br /&gt;
   System.out.println(  &amp;quot;In &amp;quot; + $y + &amp;quot; there where &amp;quot; + $pplcnt + &amp;quot; people hired&amp;quot;) &lt;br /&gt;
   insert(new PeopleHiredInYear($y))&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Exercises ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;25.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find the average salary for every post.&lt;br /&gt;
&lt;br /&gt;
  ANALYST    3000.000000 &lt;br /&gt;
  CLERK      1037.500000 &lt;br /&gt;
  MANAGER    2758.333333 &lt;br /&gt;
  PRESIDENT  5000.000000 &lt;br /&gt;
  SALESMAN   1400.000000 &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;27.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find the average annual salaries in departments.&lt;br /&gt;
&lt;br /&gt;
  10      35000.000000    &lt;br /&gt;
  20      26100.000000    &lt;br /&gt;
  30      18800.000000    &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;43.  *Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find post filled both in 1982 and 1983.&lt;br /&gt;
&lt;br /&gt;
 CLERK&lt;br /&gt;
&lt;br /&gt;
=== Filtering down results of an accumulate function ⌘===&lt;br /&gt;
Find jobs with an average salary greater than 2000&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
   Emp(j: job) and  not SalByJob(j == job)&lt;br /&gt;
   accumulate (e :Emp(job == j), &lt;br /&gt;
   	$avg : average(e.sal),&lt;br /&gt;
   	$min : min(e.sal),&lt;br /&gt;
   	$max : max(e.sal)&lt;br /&gt;
    	) &lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Number(doubleValue &amp;gt; 2000) from $avg&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 then    &lt;br /&gt;
    System.out.println(&lt;br /&gt;
    &amp;quot;Salaries in position &amp;quot; + j + &amp;quot;\n&amp;quot; +&lt;br /&gt;
     &amp;quot;Average salary: &amp;quot; + $avg + &amp;quot;\n&amp;quot; +&lt;br /&gt;
    &amp;quot;Min salary: &amp;quot; + $min + &amp;quot;\n&amp;quot; +&lt;br /&gt;
    &amp;quot;Max salary: &amp;quot; + $max + &amp;quot;\n&amp;quot;&lt;br /&gt;
 )&lt;br /&gt;
     insert(new SalByJob(j,$avg))&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Comparing to SQL:&lt;br /&gt;
 SELECT job, avg(sal) &lt;br /&gt;
 FROM Emp &lt;br /&gt;
 GROUP BY job &lt;br /&gt;
 HAVING avg(sal) &amp;gt; 2000;&lt;br /&gt;
&lt;br /&gt;
===Exercises ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;28.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find departments with more than 3 workers.&lt;br /&gt;
&lt;br /&gt;
  20      5        &lt;br /&gt;
  30      6&lt;br /&gt;
&lt;br /&gt;
== Advanced Examples ⌘==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Select employees whose salary is greater than the company&amp;#039;s average&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
 when&lt;br /&gt;
    accumulate (Emp(s : sal),avg: average(s))&lt;br /&gt;
    e: Emp(sal &amp;gt; avg)  &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot; earns &amp;quot; + e.sal + &amp;quot; the average is &amp;quot; + java.lang.Math.round(avg))&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
 when&lt;br /&gt;
  Number(avg : longValue) from accumulate (Emp(s: sal),average(s))&lt;br /&gt;
  e: Emp(sal &amp;gt; avg)  &lt;br /&gt;
 then    &lt;br /&gt;
  System.out.println(e.name + &amp;quot; earns &amp;quot; + e.sal + &amp;quot; the average is &amp;quot; + avg)&lt;br /&gt;
&lt;br /&gt;
 CARNEGIE earns 3000 the average is 2073&lt;br /&gt;
 TOOSK earns 3000 the average is 2073&lt;br /&gt;
 MERKEL earns 2450 the average is 2073&lt;br /&gt;
 BLAIR earns 2850 the average is 2073&lt;br /&gt;
 PUTIN earns 2975 the average is 2073&lt;br /&gt;
 BUSH earns 5000 the average is 2073&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
What if we want to find all the people working in the same position (job) as Blair.&lt;br /&gt;
&lt;br /&gt;
 when&lt;br /&gt;
   blr:  Emp(name == &amp;quot;BLAIR&amp;quot;)&lt;br /&gt;
   e: Emp(job == blr.job)  &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot; works as &amp;quot; + e.job)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 PUTIN works as MANAGER&lt;br /&gt;
 MERKEL works as MANAGER&lt;br /&gt;
 BLAIR works as MANAGER&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We want to find the employees earning the most in department 20.&lt;br /&gt;
&lt;br /&gt;
 when &lt;br /&gt;
   Number($max : intValue) from accumulate (Emp(s: sal,deptno == 20 ), max(s))&lt;br /&gt;
   e : Emp(deptno == 20,sal == $max) &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot; &amp;quot; + e.deptno +&amp;quot; &amp;quot; + e.sal )&lt;br /&gt;
&lt;br /&gt;
 CARNEGIE 20 3000&lt;br /&gt;
 TOOSK 20 3000&lt;br /&gt;
&lt;br /&gt;
We want to find out who earns the most in each department.&lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample&amp;quot;&lt;br /&gt;
 when&lt;br /&gt;
   Dept(dn :deptno)&lt;br /&gt;
   Number($max : longValue) from accumulate (Emp(s: sal,deptno == dn ), max(s))&lt;br /&gt;
 e : Emp(deptno == dn,sal == $max)&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(e.name + &amp;quot; &amp;quot; + e.deptno +&amp;quot; &amp;quot; + e.sal )&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 CARNEGIE 20 3000&lt;br /&gt;
 TOOSK 20 3000&lt;br /&gt;
 BLAIR 30 2850&lt;br /&gt;
 BUSH 10 5000&lt;br /&gt;
&lt;br /&gt;
===Exercises===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;45.  Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find employees earning more than the manager’s (job==&amp;#039;MANAGER&amp;#039;) average.&lt;br /&gt;
&lt;br /&gt;
  BUSH      5000.00 &lt;br /&gt;
  BLAIR     2850.00 &lt;br /&gt;
  PUTIN     2975.00 &lt;br /&gt;
  TOOSK     3000.00 &lt;br /&gt;
  CARNEGIE  3000.00 &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;46.  Exercise* &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Select employees earning the maximum salaries in their positions (jobs).&lt;br /&gt;
&lt;br /&gt;
  ELISON    CLERK      1300.00 &lt;br /&gt;
  BAROSSO   SALESMAN   1600.00 &lt;br /&gt;
  PUTIN     MANAGER    2975.00 &lt;br /&gt;
  TOOSK     ANALYST    3000.00 &lt;br /&gt;
  CARNEGIE  ANALYST    3000.00 &lt;br /&gt;
  BUSH      PRESIDENT  5000.00&lt;br /&gt;
&lt;br /&gt;
== Forall and Exists ⌘==&lt;br /&gt;
&lt;br /&gt;
Does anyone earn less than 6000?&lt;br /&gt;
In other words, do all people earn less than 6000?&lt;br /&gt;
 when &lt;br /&gt;
    forall($e : Emp(sal &amp;lt; 6000) )           &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(&amp;quot;Everyone earns less than 6000&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Are there any people earning more than 3000?&lt;br /&gt;
 when &lt;br /&gt;
    exists( Emp(sal &amp;gt; 3000))            &lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(&amp;quot;There are people earning more than 3000&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let’s find employees who have subordinates.&lt;br /&gt;
&lt;br /&gt;
 when &lt;br /&gt;
  m : Emp()&lt;br /&gt;
  exists( Emp(mgr == m.id))&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(m.name )&lt;br /&gt;
&lt;br /&gt;
 MERKEL&lt;br /&gt;
 CARNEGIE&lt;br /&gt;
 TOOSK&lt;br /&gt;
 PUTIN&lt;br /&gt;
 BLAIR&lt;br /&gt;
 BUSH&lt;br /&gt;
&lt;br /&gt;
Find workerless departments.&lt;br /&gt;
&lt;br /&gt;
 when &lt;br /&gt;
  d : Dept()&lt;br /&gt;
  not( Emp(deptno == d.deptno))&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println(d.dname )&lt;br /&gt;
&lt;br /&gt;
 OPERATIONS&lt;br /&gt;
&lt;br /&gt;
=== Exercises ===&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;49. 	Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Select employees earning maximum salaries in their positions (jobs).&lt;br /&gt;
 +----------+-----------+---------+&lt;br /&gt;
 | ename    | job       | sal     |&lt;br /&gt;
 +----------+-----------+---------+&lt;br /&gt;
 | ELISON   | CLERK     | 1300.00 |&lt;br /&gt;
 | BAROSSO  | SALESMAN  | 1600.00 |&lt;br /&gt;
 | PUTIN    | MANAGER   | 2975.00 |&lt;br /&gt;
 | TOOSK    | ANALYST   | 3000.00 |&lt;br /&gt;
 | CARNEGIE | ANALYST   | 3000.00 |&lt;br /&gt;
 | BUSH     | PRESIDENT | 5000.00 |&lt;br /&gt;
 +----------+-----------+---------+&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;51. 	Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Find employees earning more than the average salary in their department.&lt;br /&gt;
 +----------+---------+--------+&lt;br /&gt;
 | ename    | sal     | deptno |&lt;br /&gt;
 +----------+---------+--------+&lt;br /&gt;
 | BUSH     | 5000.00 | 10     |&lt;br /&gt;
 | BLAIR    | 2850.00 | 30     |&lt;br /&gt;
 | PUTIN    | 2975.00 | 20     |&lt;br /&gt;
 | BAROSSO  | 1600.00 | 30     |&lt;br /&gt;
 | TOOSK    | 3000.00 | 20     |&lt;br /&gt;
 | CARNEGIE | 3000.00 | 20     |&lt;br /&gt;
 +----------+---------+--------+&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;54. 	*Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Find employees who have no boss.&lt;br /&gt;
   BUSH&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;55. 	*Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find the maximum average salary of departments.&lt;br /&gt;
 10     2916.666667&lt;br /&gt;
&lt;br /&gt;
== Collect ==&lt;br /&gt;
Element &amp;#039;&amp;#039;&amp;#039;collect&amp;#039;&amp;#039;&amp;#039; allows rules to reason over a collection of objects obtained from the given source or from the working memory.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
rule &amp;quot;Sample1&amp;quot;&lt;br /&gt;
when &lt;br /&gt;
 $emps : ArrayList () from collect (Emp())&lt;br /&gt;
then    &lt;br /&gt;
  System.out.println(&amp;quot;No of employees: &amp;quot; + $emps.size() )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The result pattern of collect can be any concrete class that implements the java.util.Collection interface and provides a default no-arg public constructor e.g. ArrayList, LinkedList, HashSet, etc., or your own class, as long as it implements the java.util.Collection interface and provide a default no-arg public constructor.&lt;br /&gt;
&lt;br /&gt;
Find departments employing more than 3 people.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 rule &amp;quot;Sample2&amp;quot;&lt;br /&gt;
 when &lt;br /&gt;
  $d : Dept()&lt;br /&gt;
  $emps : ArrayList (&amp;#039;&amp;#039;&amp;#039;size &amp;gt; 3&amp;#039;&amp;#039;&amp;#039;)&lt;br /&gt;
        from collect (Emp(deptno == $d.deptno))&lt;br /&gt;
 then    &lt;br /&gt;
   System.out.println($d.dname )&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
=== Exercises ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;56. 	Exercise &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Find job posts having more than 2 employees.&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fstachecki</name></author>
	</entry>
</feed>