diff --git a/sql/triggers.mysql b/sql/triggers.mysql
new file mode 100644
index 0000000000000000000000000000000000000000..6ebe730dab9ae8ee2fe5f6cb4d203686a28b10de
--- /dev/null
+++ b/sql/triggers.mysql
@@ -0,0 +1,28 @@
+
+CREATE TRIGGER add_job AFTER INSERT ON job
+FOR EACH ROW
+    UPDATE analysis_stats SET
+        total_job_count     = total_job_count     + 1,
+        unclaimed_job_count = unclaimed_job_count + (CASE NEW.status WHEN 'READY'  THEN 1                         ELSE 0 END),
+        done_job_count      = done_job_count      + (CASE NEW.status WHEN 'DONE'   THEN 1 WHEN 'PASSED_ON' THEN 1 ELSE 0 END),
+        failed_job_count    = failed_job_count    + (CASE NEW.status WHEN 'FAILED' THEN 1                         ELSE 0 END),
+        status              = (CASE WHEN status!='BLOCKED' THEN 'LOADING' ELSE 'BLOCKED' END)
+    WHERE analysis_id = NEW.analysis_id;
+
+CREATE TRIGGER delete_job AFTER DELETE ON job
+FOR EACH ROW
+    UPDATE analysis_stats SET
+        total_job_count     = total_job_count     - 1,
+        unclaimed_job_count = unclaimed_job_count - (CASE OLD.status WHEN 'READY'  THEN 1                         ELSE 0 END),
+        done_job_count      = done_job_count      - (CASE OLD.status WHEN 'DONE'   THEN 1 WHEN 'PASSED_ON' THEN 1 ELSE 0 END),
+        failed_job_count    = failed_job_count    - (CASE OLD.status WHEN 'FAILED' THEN 1                         ELSE 0 END)
+    WHERE analysis_id = OLD.analysis_id;
+
+CREATE TRIGGER update_job AFTER UPDATE ON job
+FOR EACH ROW
+    UPDATE analysis_stats SET
+        unclaimed_job_count = unclaimed_job_count + (CASE NEW.status WHEN 'READY'  THEN 1 WHEN 'CLAIMED'   THEN -1 ELSE 0 END),
+        done_job_count      = done_job_count      + (CASE NEW.status WHEN 'DONE'   THEN 1 WHEN 'PASSED_ON' THEN  1 ELSE 0 END),
+        failed_job_count    = failed_job_count    + (CASE NEW.status WHEN 'FAILED' THEN 1                          ELSE 0 END)
+    WHERE analysis_id = NEW.analysis_id;
+
diff --git a/sql/triggers.sqlite b/sql/triggers.sqlite
new file mode 100644
index 0000000000000000000000000000000000000000..ee3ce4e57d7d9f35701f66f87dcb4ba5ed2115df
--- /dev/null
+++ b/sql/triggers.sqlite
@@ -0,0 +1,34 @@
+
+CREATE TRIGGER add_job AFTER INSERT ON job
+FOR EACH ROW
+BEGIN
+    UPDATE analysis_stats SET
+        total_job_count     = total_job_count     + 1,
+        unclaimed_job_count = unclaimed_job_count + (CASE NEW.status WHEN 'READY'  THEN 1                         ELSE 0 END),
+        done_job_count      = done_job_count      + (CASE NEW.status WHEN 'DONE'   THEN 1 WHEN 'PASSED_ON' THEN 1 ELSE 0 END),
+        failed_job_count    = failed_job_count    + (CASE NEW.status WHEN 'FAILED' THEN 1                         ELSE 0 END),
+        status              = (CASE WHEN status!='BLOCKED' THEN 'LOADING' ELSE 'BLOCKED' END)
+    WHERE analysis_id = NEW.analysis_id;
+END;
+
+CREATE TRIGGER delete_job AFTER DELETE ON job
+FOR EACH ROW
+BEGIN
+    UPDATE analysis_stats SET
+        total_job_count     = total_job_count     - 1,
+        unclaimed_job_count = unclaimed_job_count - (CASE OLD.status WHEN 'READY'  THEN 1                         ELSE 0 END),
+        done_job_count      = done_job_count      - (CASE OLD.status WHEN 'DONE'   THEN 1 WHEN 'PASSED_ON' THEN 1 ELSE 0 END),
+        failed_job_count    = failed_job_count    - (CASE OLD.status WHEN 'FAILED' THEN 1                         ELSE 0 END)
+    WHERE analysis_id = OLD.analysis_id;
+END;
+
+CREATE TRIGGER update_job AFTER UPDATE ON job
+FOR EACH ROW
+BEGIN
+    UPDATE analysis_stats SET
+        unclaimed_job_count = unclaimed_job_count + (CASE NEW.status WHEN 'READY'  THEN 1 WHEN 'CLAIMED'   THEN -1 ELSE 0 END),
+        done_job_count      = done_job_count      + (CASE NEW.status WHEN 'DONE'   THEN 1 WHEN 'PASSED_ON' THEN  1 ELSE 0 END),
+        failed_job_count    = failed_job_count    + (CASE NEW.status WHEN 'FAILED' THEN 1                          ELSE 0 END)
+    WHERE analysis_id = NEW.analysis_id;
+END;
+