diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php
index b28a0fe1983b3cc30bef18568a1f5a1cdc194101..d0e2d5331a1f8fba16498410686aff5bb3d4b6c3 100644
--- a/app/controllers/admin/courses.php
+++ b/app/controllers/admin/courses.php
@@ -375,14 +375,14 @@ class Admin_CoursesController extends AuthenticatedController
         }
         PluginEngine::sendMessage(AdminCourseWidgetPlugin::class, 'applyFilters', $filter);
 
-        $count = $filter->countCourses();
-        if ($count > $this->max_show_courses && !Request::submitted('without_limit')) {
-            $this->render_json([
-                'count' => $count
-            ]);
+        try {
+            $courses = $filter->fetchCourses(
+                Request::bool('without_limit') ? null: $this->max_show_courses
+            );
+        } catch (OverflowException $e) {
+            $this->render_json(['count' => (int) $e->getMessage()]);
             return;
         }
-        $courses = AdminCourseFilter::get()->getCourses();
 
         $data = [
             'data' => []
diff --git a/lib/classes/AdminCourseFilter.class.php b/lib/classes/AdminCourseFilter.class.php
index da8ce54f7e055ad8771f3d79e7c8bda739fd9087..3b9cb4ba6a2894e3326cd75c98795cafe54f70cd 100644
--- a/lib/classes/AdminCourseFilter.class.php
+++ b/lib/classes/AdminCourseFilter.class.php
@@ -28,6 +28,8 @@
 class AdminCourseFilter
 {
     static protected $instance = null;
+
+    /** @var SQLQuery|null  */
     public $query = null;
     public $max_show_courses = 500;
     public $settings = [];
@@ -109,13 +111,10 @@ class AdminCourseFilter
         }
 
         if (Config::get()->ALLOW_ADMIN_RELATED_INST) {
-            $sem_inst = 'seminar_inst';
-            $this->query->join('seminar_inst', 'seminar_inst', 'seminar_inst.seminar_id = seminare.Seminar_id');
+            $this->query->where('seminar_inst', 'EXISTS (SELECT 1 FROM seminar_inst WHERE seminar_id = seminare.Seminar_id AND institut_id IN (:institut_ids))');
         } else {
-            $sem_inst = 'seminare';
+            $this->query->where("seminar_inst", "seminare.institut_id IN (:institut_ids)");
         }
-
-        $this->query->where('seminar_inst', "$sem_inst.institut_id IN (:institut_ids)");
         $this->query->parameter('institut_ids', $inst_ids);
 
         if ($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE) {
@@ -195,6 +194,16 @@ class AdminCourseFilter
         return $this->query->count();
     }
 
+    /**
+     * @param int|null $limit
+     * @return Course[]
+     */
+    public function fetchCourses(?int $limit = null): array
+    {
+        NotificationCenter::postNotification('AdminCourseFilterWillQuery', $this);
+        return $this->query->fetchAll(Course::class, $limit);
+    }
+
     /**
      * Returns the data of the resultset of the AdminCourseFilter.
      *
@@ -206,16 +215,16 @@ class AdminCourseFilter
      */
     public function getCoursesForAdminWidget(string $order_by = 'name')
     {
-        $count_courses = $this->countCourses();
-        $order = 'seminare.name';
-        if ($order_by === 'number') {
-            $order = 'seminare.veranstaltungsnummer, seminare.name';
-        }
-        if ($count_courses && $count_courses <= $this->max_show_courses) {
+        try {
+            $order = 'seminare.name';
+            if ($order_by === 'number') {
+                $order = 'seminare.veranstaltungsnummer, seminare.name';
+            }
             $this->query->orderBy($order);
-            return $this->getCourses();
+            return $this->fetchCourses($this->max_show_courses);
+        } catch (OverflowException $e) {
+            return [];
         }
-        return [];
     }
 
 }
diff --git a/lib/classes/SQLQuery.php b/lib/classes/SQLQuery.php
index 0442604ff6e2933bd411c9c5e8ac58e56254234c..6c8f49ec7d3a1ba1577d3324215297fcc61db568 100644
--- a/lib/classes/SQLQuery.php
+++ b/lib/classes/SQLQuery.php
@@ -215,14 +215,22 @@ class SQLQuery
     /**
      * Fetches the whole resultset as an array of associative arrays. If you define
      * a sorm_class the result will be an array of the sorm-objects.
-     * @param $sorm_class_or_column : column name, a class of SimpleORMap or null for associative array.
-     * @return array of arrays or array of objects or array of values.
+     *
+     * @template T of SimpleORMap
+     * @param class-string<T>|string|null $sorm_class_or_column : column name, a class of SimpleORMap or null for associative array.
+     * @param int|null $max_results Maximum number of results to return
+     * @return array[]|T[]|mixed[] arrays or array of objects or array of values.
+     *
+     * @throws OverflowException if number of found rows is greater than $max_results
      */
-    public function fetchAll($sorm_class_or_column = null)
+    public function fetchAll($sorm_class_or_column = null, ?int $max_results = null)
     {
         NotificationCenter::postNotification('SQLQueryWillExecute', $this);
 
-        if (is_string($sorm_class_or_column) && !is_subclass_of($sorm_class_or_column, "SimpleORMap")) {
+        if (
+            is_string($sorm_class_or_column)
+            && !is_subclass_of($sorm_class_or_column, SimpleORMap::class)
+        ) {
             $sql = "SELECT `{$this->settings['table']}`.`{$sorm_class_or_column}` ";
         } else {
             $sql = "SELECT `{$this->settings['table']}`.* ";
@@ -239,16 +247,31 @@ class SQLQuery
 
         NotificationCenter::postNotification('SQLQueryDidExecute', $this);
 
-        if (is_string($sorm_class_or_column) && !is_subclass_of($sorm_class_or_column, "SimpleORMap")) {
-            return $statement->fetchAll(PDO::FETCH_COLUMN, 0);
+        if (
+            is_string($sorm_class_or_column)
+            && !is_subclass_of($sorm_class_or_column, SimpleORMap::class)
+        ) {
+            return $statement->fetchAll(PDO::FETCH_COLUMN);
         }
 
-        $alldata = $statement->fetchAll(PDO::FETCH_ASSOC);
-        if (!$sorm_class_or_column) {
-            return $alldata;
+        $statement->setFetchMode(PDO::FETCH_ASSOC);
+
+        $result = [];
+        $count = 0;
+        foreach ($statement as $row) {
+            $result[$count++] = $sorm_class_or_column ? $sorm_class_or_column::buildExisting($row) : $row;
+
+            if ($max_results && $count > $max_results) {
+                // Count remaining rows
+                $statement->setFetchMode(PDO::FETCH_COLUMN, 0);
+                while ($statement->fetch()) {
+                    $count += 1;
+                }
+                throw new OverflowException($count);
+            }
         }
 
-        return array_map("{$sorm_class_or_column}::buildExisting", $alldata);
+        return $result;
     }
 
     /**