diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h
index 7be9d18ebf117942507ad33e26b13370bd56138a..f4332883791efe889d6683cbb5ed29fed88592ff 100644
--- a/include/caosdb/transaction.h
+++ b/include/caosdb/transaction.h
@@ -368,6 +368,17 @@ public:
     return *result_set;
   }
 
+  /**
+   * Return the result of a count query
+   *
+   * Only meaningful if there was exactly one COUNT query executed in
+   * this transaction. In all other cases, the return value will be
+   * -1.
+   */
+  [[nodiscard]] inline auto GetCountResult() const -> int {
+    return query_count;
+  }
+
   /**
    * Return the number of sub-requests in this transaction.
    *
@@ -394,6 +405,7 @@ private:
   MultiTransactionRequest *request;
   mutable MultiTransactionResponse *response;
   std::string error_message;
+  mutable long query_count;
 };
 
 template <class InputIterator>
diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp
index 698218a820c403a60eb322fedf8cf58228a6c11b..f866ca337a382fab7d8a0d7032ed3600be886e7a 100644
--- a/src/caosdb/transaction.cpp
+++ b/src/caosdb/transaction.cpp
@@ -96,6 +96,8 @@ using caosdb::entity::v1alpha1::MultiTransactionRequest;
 using caosdb::entity::v1alpha1::MultiTransactionResponse;
 using WrappedResponseCase =
   caosdb::entity::v1alpha1::TransactionResponse::WrappedResponseCase;
+using QueryResponseCase =
+  caosdb::entity::v1alpha1::RetrieveResponse::QueryResponseCase;
 using caosdb::utility::get_arena;
 using grpc::ClientAsyncResponseReader;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
@@ -146,6 +148,7 @@ Transaction::Transaction(
     response(google::protobuf::Arena::CreateMessage<MultiTransactionResponse>(
       get_arena())) {
   this->service_stub = std::move(service_stub);
+  this->query_count = -1;
 }
 
 auto Transaction::RetrieveById(const std::string &id) noexcept -> StatusCode {
@@ -282,12 +285,26 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus {
     auto *responses = this->response->mutable_responses(0);
     switch (responses->wrapped_response_case()) {
     case WrappedResponseCase::kRetrieveResponse: {
-      auto *entity = responses->mutable_retrieve_response()->release_entity();
-      if (!entity->errors().empty()) {
-        this->status = TransactionStatus::TRANSACTION_ERROR(
-          "The request returned with errors.");
+      auto *retrieve_response = responses->mutable_retrieve_response();
+      switch (retrieve_response->query_response_case()) {
+      case QueryResponseCase::kEntity: {
+        auto *entity = retrieve_response->release_entity();
+        if (!entity->errors().empty()) {
+          this->status = TransactionStatus::TRANSACTION_ERROR(
+            "The request returned with errors.");
+        }
+        this->result_set = std::make_unique<UniqueResult>(entity);
+      } break;
+      case QueryResponseCase::kSelectResult: {
+        // TODO(tf) Select queries
+      } break;
+      case QueryResponseCase::kCountResult: {
+        this->query_count = retrieve_response->count_result();
+      } break;
+      default:
+        // TODO(tf) Error
+        break;
       }
-      this->result_set = std::make_unique<UniqueResult>(entity);
     } break;
     case WrappedResponseCase::kUpdateResponse: {
       auto *updatedIdResponse = responses->mutable_update_response();