diff --git a/include/class.orm.php b/include/class.orm.php
index c004ab455bd3c43252cdcb42947b78aaf2c1befe..1f3631db3bfc4a94a639ab4264782b6d39cfa646 100644
--- a/include/class.orm.php
+++ b/include/class.orm.php
@@ -728,8 +728,9 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl
         return $this;
     }
 
-    function order_by() {
-        $this->ordering = array_merge($this->ordering, func_get_args());
+    function order_by($order) {
+        $this->ordering = array_merge($this->ordering,
+            is_array($order) ?  $order : func_get_args());
         return $this;
     }
     function getSortFields() {
@@ -754,6 +755,10 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl
         return $this;
     }
 
+    function isWindowed() {
+        return $this->limit || $this->offset;
+    }
+
     function select_related() {
         $this->related = array_merge($this->related, func_get_args());
         return $this;
@@ -945,6 +950,26 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl
         return $this->query;
     }
 
+    function asView() {
+        $unique = spl_object_hash($this);
+        $classname = "QueryView{$unique}";
+        $class = <<<EOF
+class {$classname} extends VerySimpleModel {
+    static \$meta = array(
+        'view' => true,
+    );
+    static \$queryset;
+
+    static function getQuery(\$compiler) {
+        return ' ('.static::\$queryset->getQuery().') ';
+    }
+}
+EOF;
+        eval($class); // Ugh
+        $classname::$queryset = $this;
+        return $classname;
+    }
+
     function serialize() {
         $info = get_object_vars($this);
         unset($info['query']);
@@ -1681,6 +1706,14 @@ class MySqlCompiler extends SqlCompiler {
             $vals = array_map(array($this, 'input'), $b);
             $b = implode(', ', $vals);
         }
+        // MySQL doesn't support LIMIT or OFFSET in subqueries. Instead, add
+        // add the constraint to the join
+        elseif ($b instanceof QuerySet && $b->isWindowed()) {
+            $f1 = $b->values[0];
+            $view = $b->asView();
+            $alias = $this->pushJoin($view, $a, $view, array('constraint'=>array()));
+            return sprintf('%s = %s.%s', $a, $alias, $this->quote($f1));
+        }
         else {
             $b = $this->input($b);
         }
@@ -1744,12 +1777,16 @@ class MySqlCompiler extends SqlCompiler {
         if ($extra instanceof Q) {
             $constraints[] = $this->compileQ($extra, $model, self::SLOT_JOINS);
         }
+        if (!isset($rmodel))
+            $rmodel = $model;
         // Support inline views
         $table = ($rmodel::$meta['view'])
             ? $rmodel::getQuery($this)
             : $this->quote($rmodel::$meta['table']);
-        return $join.$table
-            .' '.$alias.' ON ('.implode(' AND ', $constraints).')';
+        $base = $join.$table.$alias;
+        if ($constraints)
+            $base .= ' ON ('.implode(' AND ', $constraints).')';
+        return $base;
     }
 
     /**
@@ -1992,7 +2029,7 @@ class MySqlCompiler extends SqlCompiler {
             foreach ($queryset->distinct as $d)
                 list($group_by[]) = $this->getField($d, $model);
         }
-        $group_by = $group_by ? ' GROUP BY '.implode(',', $group_by) : '';
+        $group_by = $group_by ? ' GROUP BY '.implode(', ', $group_by) : '';
 
         $joins = $this->getJoins($queryset);
 
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index ca01e03ddb0383ba6451abeeffcf2a85dba5f0b5..45ee6847be6da3a2b4ea031731f12849712ed88e 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -111,18 +111,18 @@ if (!$view_all_tickets) {
     $tickets->filter(Q::any($visibility));
 }
 
-// Add in annotations
-$tickets->annotate(array(
-    'collab_count' => SqlAggregate::COUNT('thread__collaborators'),
-    'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'),
-    'thread_count' => SqlAggregate::COUNT('thread__entries'),
-));
+// Apply requested quick filter
 
-// Select pertinent columns
-// ------------------------------------------------------------
-$tickets->values('lock__staff_id', 'staff_id', 'isoverdue', 'team_id', 'ticket_id', 'number', 'cdata__subject', 'user__default_email__address', 'source', 'cdata__:priority__priority_color', 'cdata__:priority__priority_desc', 'status_id', 'status__name', 'status__state', 'dept_id', 'dept__name', 'user__name', 'lastupdate');
+// Rewrite $tickets to use a nested query, which will include the LIMIT part
+// in order to speed the result
 
-// Apply requested quick filter
+// Apply requested pagination
+$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
+$pageNav = new Pagenate($tickets->count(), $page, PAGE_LIMIT);
+$pageNav->setURL('tickets.php', $args);
+$tickets = $pageNav->paginate($tickets);
+
+$tickets2 = TicketModel::objects();
 
 // Apply requested sorting
 $queue_sort_key = sprintf(':Q:%s:sort', $queue_name);
@@ -156,14 +156,26 @@ case 'updated':
     break;
 }
 
-// Apply requested pagination
-$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
-$pageNav=new Pagenate($tickets->count(), $page, PAGE_LIMIT);
-$pageNav->setURL('tickets.php', $args);
-$tickets = $pageNav->paginate($tickets);
+$tickets2 = TicketModel::objects();
+$tickets2->filter(array('ticket_id__in' => $tickets->values_flat('ticket_id')));
+
+// Transfer the order_by from the original tickets
+$tickets2->order_by($tickets->getSortFields());
+$tickets = $tickets2;
 
 TicketForm::ensureDynamicDataView();
 
+// Select pertinent columns
+// ------------------------------------------------------------
+$tickets->values('lock__staff_id', 'staff_id', 'isoverdue', 'team_id', 'ticket_id', 'number', 'cdata__subject', 'user__default_email__address', 'source', 'cdata__:priority__priority_color', 'cdata__:priority__priority_desc', 'status_id', 'status__name', 'status__state', 'dept_id', 'dept__name', 'user__name', 'lastupdate');
+
+// Add in annotations
+$tickets->annotate(array(
+    'collab_count' => SqlAggregate::COUNT('thread__collaborators'),
+    'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'),
+    'thread_count' => SqlAggregate::COUNT('thread__entries'),
+));
+
 // Save the query to the session for exporting
 $_SESSION[':Q:tickets'] = $tickets;