diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64b09402bc3f762a771a6df118ab8ccdc5b4553e..9bd479a63f27e29fd930ae5f087692f1d8d4307f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,8 +18,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Removed
 
+* `IdOnly` flag (see https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/187).
+  The flags was not working anyways. However, `SELECT id FROM ...` queries are
+  now optimized in the way the `IdOnly` flag was supposed to do.
+
 ### Fixed
 
+* #181 CQL's `UPDATED` filter.
+  (https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/181)
 * #183 No reasonable error when using bad datetime format.
   (https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/183)
 * #127 "nan" as value (list item) in properties with data type "LIST<DOUBLE>"
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertTransactionHistory.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertTransactionHistory.java
index 6282ede52aa514353c21f0b8dd3345a85305725b..32f628459b4a8e3a23b9ac3d047e723d7a837c28 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertTransactionHistory.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertTransactionHistory.java
@@ -26,6 +26,8 @@ import org.caosdb.server.database.BackendTransaction;
 import org.caosdb.server.database.backend.interfaces.InsertTransactionHistoryImpl;
 import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.InsertEntity;
+import org.caosdb.server.entity.UpdateEntity;
 import org.caosdb.server.entity.container.TransactionContainer;
 import org.caosdb.server.utils.EntityStatus;
 
@@ -60,7 +62,8 @@ public class InsertTransactionHistory extends BackendTransaction {
 
     for (final EntityInterface e : this.container) {
       if (e.getEntityStatus() == EntityStatus.DELETED
-          || e.getEntityStatus() == EntityStatus.VALID) {
+          || (e instanceof UpdateEntity && e.getEntityStatus() == EntityStatus.QUALIFIED)
+          || (e instanceof InsertEntity && e.getEntityStatus() == EntityStatus.VALID)) {
 
         t.execute(
             e.getClass().getSimpleName().replace("Entity", ""),
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java
index 6bac0ff187fe2a08d2d0c1c7450ac954bc023d5e..e42b854e3284017059f8d0f6bf83a70ddfdfc165 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java
@@ -101,6 +101,9 @@ public class RetrieveFullEntityTransaction extends BackendTransaction {
    * @param selections
    */
   public void retrieveFullEntity(EntityInterface e, List<Selection> selections) {
+    if (!needMoreThanId(selections)) {
+      return;
+    }
     execute(new RetrieveSparseEntity(e));
 
     if (e.getEntityStatus() == EntityStatus.VALID) {
@@ -108,8 +111,13 @@ public class RetrieveFullEntityTransaction extends BackendTransaction {
       if (e.getRole() == Role.QueryTemplate) {
         execute(new RetrieveQueryTemplateDefinition(e));
       }
-      execute(new RetrieveParents(e));
-      execute(new RetrieveProperties(e));
+      if (needParents(selections)) {
+        execute(new RetrieveParents(e));
+      }
+
+      if (needProperties(selections)) {
+        execute(new RetrieveProperties(e));
+      }
 
       // recursion! retrieveSubEntities calls retrieveFull sometimes, but with reduced selectors.
       if (selections != null && !selections.isEmpty()) {
@@ -118,6 +126,55 @@ public class RetrieveFullEntityTransaction extends BackendTransaction {
     }
   }
 
+  /**
+   * Return true iff anything else than the id is needed for this retrieval.
+   *
+   * <p>The notorious case, where it is not necessary to retrieve the sparse entity is during
+   * `SELECT id FROM ...` queries.
+   */
+  private boolean needMoreThanId(List<Selection> selections) {
+    if (selections == null || selections.isEmpty()) {
+      return true;
+    } else if (selections.size() == 1 && selections.get(0).isId()) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Return true iff the properties need to be retrieved.
+   *
+   * <p>It is not necessary during `SELECT parent, name, version, ...` queries where no actual
+   * properties are being selected.
+   */
+  private boolean needProperties(List<Selection> selections) {
+    if (selections == null || selections.isEmpty()) {
+      return true;
+    }
+    for (Selection s : selections) {
+      if (s.isProperty()) {
+        return true;
+      }
+    }
+    return false;
+  }
+  /**
+   * Return true iff the parents need to be retrieved.
+   *
+   * <p>It is not necessary during `SELECT` queries that do not select the parent.
+   */
+  private boolean needParents(List<Selection> selections) {
+    if (selections == null || selections.isEmpty()) {
+      return true;
+    }
+    for (Selection s : selections) {
+      if (s.isParent()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /**
    * Recursively resolve the reference values of the list of reference property `p` (but only the
    * selected sub-properties).
diff --git a/src/main/java/org/caosdb/server/jobs/core/RetrieveIdOnlyFlag.java b/src/main/java/org/caosdb/server/jobs/core/RetrieveIdOnlyFlag.java
deleted file mode 100644
index 844468c5473b4d2dff6e59777f925f2701505749..0000000000000000000000000000000000000000
--- a/src/main/java/org/caosdb/server/jobs/core/RetrieveIdOnlyFlag.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-package org.caosdb.server.jobs.core;
-
-import org.caosdb.server.entity.EntityInterface;
-import org.caosdb.server.jobs.FlagJob;
-import org.caosdb.server.jobs.JobAnnotation;
-import org.caosdb.server.jobs.TransactionStage;
-import org.caosdb.server.utils.EntityStatus;
-
-@JobAnnotation(flag = "IdOnly", stage = TransactionStage.PRE_TRANSACTION)
-public class RetrieveIdOnlyFlag extends FlagJob {
-
-  @Override
-  protected void job(final String value) {
-    if (value == null || value.equalsIgnoreCase("true")) {
-      for (final EntityInterface e : getContainer()) {
-        // do not retrieve this entity
-        e.setEntityStatus(EntityStatus.IGNORE);
-      }
-    }
-  }
-}
diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java
index dca63841df3ee1a5efa4148d24e3e8eb68cd2f50..22a513f6775c9187a9a055cd92048c45f64c5cc4 100644
--- a/src/main/java/org/caosdb/server/query/Query.java
+++ b/src/main/java/org/caosdb/server/query/Query.java
@@ -32,12 +32,15 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Types;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.UUID;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -75,6 +78,16 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     private final String selector;
     private Selection subselection = null;
 
+    /**
+     * These magic non-properties are those which are in the results of a {@link
+     * RetrieveSparseEntity} transaction which is why they do not need to be retrieved with a {@link
+     * RetrieveEntityProperties} transaction.
+     */
+    static final Set<String> MAGIC_NON_PROPERTIES =
+        new HashSet<>(
+            Arrays.asList(
+                new String[] {"value", "parent", "id", "name", "description", "datatype"}));
+
     public Selection setSubSelection(final Selection sub) {
       if (this.subselection != null) {
         throw new UnsupportedOperationException("SubSelection is immutable!");
@@ -111,6 +124,29 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
       ret.setAttribute("name", toString());
       return ret;
     }
+
+    /**
+     * Return true iff this selector selects the parent of an entity. If not, the retrieval in
+     * {@link RetrieveFullEntityTransaction} might be optimized by not retrieving the parents at
+     * all.
+     */
+    public boolean isParent() {
+      return this.selector.equalsIgnoreCase("parent");
+    }
+
+    /**
+     * Return true iff this selector selects anything that is most likely a property. If not, the
+     * retrieval in {@link RetrieveFullEntityTransaction} might be optimized by not retrieving the
+     * properties at all.
+     */
+    public boolean isProperty() {
+      return !MAGIC_NON_PROPERTIES.contains(this.selector.toLowerCase());
+    }
+
+    /** Return true iff this selector selects the id of an entity. */
+    public boolean isId() {
+      return this.selector.equalsIgnoreCase("id");
+    }
   }
 
   public enum Role {