diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 990ae735677c635ffbc7f1b78454e33df5282b82..9e416bef6a3961dcc549ff8381ed6bc93c2003ce 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -33,29 +33,29 @@ class TicketsAjaxAPI extends AjaxController {
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $tickets=array();
 
-        $sql='SELECT DISTINCT `number`, email.address AS email'
-            .' FROM '.TICKET_TABLE.' ticket'
-            .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
-            .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
-            .' WHERE `number` LIKE \''.db_input($_REQUEST['q'], false).'%\'';
-
-        $sql.=' AND ( staff_id='.db_input($thisstaff->getId());
-
-        if(($teams=$thisstaff->getTeams()) && count(array_filter($teams)))
-            $sql.=' OR team_id IN('.implode(',', db_input(array_filter($teams))).')';
-
-        if(!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
-            $sql.=' OR dept_id IN ('.implode(',', db_input($depts)).')';
+        $visibility = Q::any(array(
+            'staff_id' => $thisstaff->getId(),
+            'team_id__in' => $thisstaff->teams->values_flat('team_id'),
+        ));
+        if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts())) {
+            $visibility->add(array('dept_id__in' => $depts));
+        }
 
-        $sql.=' )  '
-            .' ORDER BY ticket.created LIMIT '.$limit;
 
-        if(($res=db_query($sql)) && db_num_rows($res)) {
-            while(list($id, $email)=db_fetch_row($res)) {
-                $info = "$id - $email";
-                $tickets[] = array('id'=>$id, 'email'=>$email, 'value'=>$id,
-                    'info'=>$info, 'matches'=>$_REQUEST['q']);
-            }
+        $hits = TicketModel::objects()
+            ->filter(Q::any(array(
+                'number__startswith' => $_REQUEST['q'],
+            )))
+            ->filter($visibility)
+            ->values('number', 'user__emails__address')
+            ->annotate(array('tickets' => SqlAggregate::COUNT('ticket_id')))
+            ->order_by('-created')
+            ->limit($limit);
+
+        foreach ($hits as $T) {
+            $tickets[] = array('id'=>$T['number'], 'value'=>$T['number'],
+                'info'=>"{$T['number']} — {$T['user__emails__address']}",
+                'matches'=>$_REQUEST['q']);
         }
         if (!$tickets)
             return self::lookupByEmail();
@@ -70,29 +70,31 @@ class TicketsAjaxAPI extends AjaxController {
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $tickets=array();
 
-        $sql='SELECT email.address AS email, count(ticket.ticket_id) as tickets '
-            .' FROM '.TICKET_TABLE.' ticket'
-            .' JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
-            .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
-            .' WHERE (email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\'
-                OR user.name LIKE \'%'.db_input($_REQUEST['q'], false).'%\')';
-
-        $sql.=' AND ( staff_id='.db_input($thisstaff->getId());
-
-        if(($teams=$thisstaff->getTeams()) && count(array_filter($teams)))
-            $sql.=' OR team_id IN('.implode(',', db_input(array_filter($teams))).')';
-
-        if(!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
-            $sql.=' OR dept_id IN ('.implode(',', db_input($depts)).')';
-
-        $sql.=' ) '
-            .' GROUP BY email.address '
-            .' ORDER BY ticket.created  LIMIT '.$limit;
+        $visibility = Q::any(array(
+            'staff_id' => $thisstaff->getId(),
+            'team_id__in' => $thisstaff->teams->values_flat('team_id'),
+        ));
+        if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts())) {
+            $visibility->add(array('dept_id__in' => $depts));
+        }
 
-        if(($res=db_query($sql)) && db_num_rows($res)) {
-            while(list($email, $count)=db_fetch_row($res))
-                $tickets[] = array('email'=>$email, 'value'=>$email,
-                    'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']);
+        $hits = TicketModel::objects()
+            ->filter(Q::any(array(
+                'user__emails__address__contains' => $_REQUEST['q'],
+                'user__name__contains' => $_REQUEST['q'],
+                'user__account__username' => $_REQUEST['q'],
+                'user__org__name__contains' => $_REQUEST['q'],
+            )))
+            ->filter($visibility)
+            ->values('user__emails__address')
+            ->annotate(array('tickets' => SqlAggregate::COUNT('ticket_id')))
+            ->limit($limit);
+
+        foreach ($hits as $T) {
+            $email = $T['user__emails__address'];
+            $count = $T['tickets'];
+            $tickets[] = array('email'=>$email, 'value'=>$email,
+                'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']);
         }
 
         return $this->json_encode($tickets);
diff --git a/include/class.export.php b/include/class.export.php
index 1e92c97f6d55522c2384f1837412cae44cbb07ec..288cb68480c0d850f57e91cb81938eae9fc4aa88 100644
--- a/include/class.export.php
+++ b/include/class.export.php
@@ -57,16 +57,19 @@ class Export {
             $cdata[$key] = $f->getLocal('label');
         }
         // Reset the $sql query
-        $tickets = TicketModel::objects()
-            ->filter($sql->constraints)
+        $tickets = $sql->models()
             ->select_related('user', 'user__default_email', 'dept', 'staff',
-                'team', 'staff', 'cdata');
-        call_user_func_array(array($tickets, 'order_by'), $sql->getSortFields());
+                'team', 'staff', 'cdata')
+            ->annotate(array(
+            'collab_count' => SqlAggregate::COUNT('thread__collaborators'),
+            'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'),
+            'thread_count' => SqlAggregate::COUNT('thread__entries'),
+        ));
 
         return self::dumpQuery($tickets,
             array(
                 'number' =>         __('Ticket Number'),
-                'created' =>        __('Date'),
+                'created' =>        __('Date Created'),
                 'cdata.subject' =>  __('Subject'),
                 'user.name' =>      __('From'),
                 'user.default_email.address' => __('From Email'),
@@ -75,14 +78,14 @@ class Export {
                 'topic::getName' => __('Help Topic'),
                 'source' =>         __('Source'),
                 'status::getName' =>__('Current Status'),
-                '::getEffectiveDate' => __('Last Updated'),
-                'duedate' =>        __('Due Date'),
+                'lastupdate' =>     __('Last Updated'),
+                'est_duedate' =>    __('Due Date'),
                 'isoverdue' =>      __('Overdue'),
                 'isanswered' =>     __('Answered'),
                 'staff::getName' => __('Agent Assigned'),
                 'team::getName' =>  __('Team Assigned'),
-                #'thread_count' =>   __('Thread Count'),
-                #'attachments' =>    __('Attachment Count'),
+                'thread_count' =>   __('Thread Count'),
+                'attachment_count' => __('Attachment Count'),
             ) + $cdata,
             $how,
             array('modify' => function(&$record, $keys) use ($fields) {
@@ -254,7 +257,7 @@ class ResultSetExporter {
                 }
             }
             // Evalutate :: function call on target current
-            if ($func && method_exists($current, $func)) {
+            if ($func && (method_exists($current, $func) || method_exists($current, '__call'))) {
                 $current = $current->{$func}();
             }
             $record[] = (string) $current;
diff --git a/include/class.format.php b/include/class.format.php
index 02402cf70c45f7739d103fa7d462f7e4bede45b0..7b00d4adb277432b0c1a0801dbba691beb9a2696 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -444,10 +444,6 @@ class Format {
         if ($timestamp && $fromDb) {
             $timestamp = Misc::db2gmtime($timestamp);
         }
-        elseif (!$timestamp) {
-            $D = new DateTime();
-            $timestamp = $D->getTimestamp();
-        }
         if (class_exists('IntlDateFormatter')) {
             $formatter = new IntlDateFormatter(
                 Internationalization::getCurrentLocale(),
diff --git a/include/class.orm.php b/include/class.orm.php
index c004ab455bd3c43252cdcb42947b78aaf2c1befe..ef615b39f63757fdd902ffe0627e2faf8ba9cf69 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;
@@ -772,6 +777,12 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl
         return $this;
     }
 
+    function models() {
+        $this->iterator = 'ModelInstanceManager';
+        $this->values = $this->related = array();
+        return $this;
+    }
+
     function values() {
         foreach (func_get_args() as $A)
             $this->values[$A] = $A;
@@ -945,6 +956,30 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl
         return $this->query;
     }
 
+    /**
+     * Fetch a model class which can be used to render the QuerySet as a
+     * subquery to be used as a JOIN.
+     */
+    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 +1716,15 @@ 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
+        // the query as a JOIN and add the join constraint into the WHERE
+        // clause.
+        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 +1788,17 @@ 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'])
+            // XXX: Support parameters from the nested query
             ? $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;
     }
 
     /**
@@ -1820,7 +1869,7 @@ class MySqlCompiler extends SqlCompiler {
         }
         if (isset($queryset->extra['where'])) {
             foreach ($queryset->extra['where'] as $S) {
-                $where[] = '('.$S.')';
+                $where[] = "($S)";
             }
         }
         if ($where)
@@ -1992,7 +2041,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/class.search.php b/include/class.search.php
index 84d3bbbcdc7d4478be5d1af5e733eadda3e7a323..355feb0725ce8b0fea9d9f5e1ba46c269dc312e0 100644
--- a/include/class.search.php
+++ b/include/class.search.php
@@ -304,7 +304,7 @@ class MysqlSearchBackend extends SearchBackend {
             $key = 'COALESCE(Z1.ticket_id, Z2.ticket_id)';
             $criteria->extra(array(
                 'select' => array(
-                    'key' => $key,
+                    'ticket_id' => $key,
                     'relevance'=>'`search`.`relevance`',
                 ),
                 'order_by' => array(new SqlCode('`relevance`')),
@@ -702,6 +702,7 @@ class SavedSearch extends VerySimpleModel {
     function mangleQuerySet(QuerySet $qs, $form=false) {
         $form = $form ?: $this->getForm();
         $searchable = $this->getCurrentSearchFields($form->getSource());
+        $qs = clone $qs;
 
         // Figure out fields to search on
         foreach ($form->getFields() as $f) {
diff --git a/include/staff/templates/tickets.tmpl.php b/include/staff/templates/tickets.tmpl.php
index 7fc45a41afd9328dc2b3300b16b935385e57fa76..c2d1702f5d4ca5a2935fcce111f6a536f2d46cc5 100644
--- a/include/staff/templates/tickets.tmpl.php
+++ b/include/staff/templates/tickets.tmpl.php
@@ -64,7 +64,7 @@ if ($results) { ?>
 <?php csrf_token(); ?>
  <input type="hidden" name="a" value="mass_process" >
  <input type="hidden" name="do" id="action" value="" >
- <table class="list fixed" border="0" cellspacing="1" cellpadding="2" width="940">
+ <table class="list" border="0" cellspacing="1" cellpadding="2" width="940">
     <thead>
         <tr>
             <?php
@@ -78,11 +78,11 @@ if ($results) { ?>
             <th width="380"><?php echo __('Subject'); ?></th>
             <?php
             if ($user) { ?>
-            <th width="150"><?php echo __('Department'); ?></th>
-            <th width="150"><?php echo __('Assignee'); ?></th>
+            <th width="125"><?php echo __('Department'); ?></th>
+            <th width="125"><?php echo __('Assignee'); ?></th>
             <?php
             } else { ?>
-            <th width="300"><?php echo __('User'); ?></th>
+            <th width="250"><?php echo __('User'); ?></th>
             <?php
             } ?>
         </tr>
@@ -100,8 +100,8 @@ if ($results) { ?>
         $assigned='';
         if ($T['staff_id'])
             $assigned = new PersonsName(array(
-                'first' => $row['staff__firstname'],
-                'last' => $row['staff__lastname']
+                'first' => $T['staff__firstname'],
+                'last' => $T['staff__lastname']
             ));
         elseif ($T['team_id'])
             $assigned = Team::getLocalById($T['team_id'], 'name', $T['team__name']);
@@ -128,28 +128,28 @@ if ($results) { ?>
                 title="<?php echo __('Preview Ticket'); ?>"
                 href="tickets.php?id=<?php echo $T['ticket_id']; ?>"
                 data-preview="#tickets/<?php echo $T['ticket_id']; ?>/preview"><?php echo $tid; ?></a></td>
-            <td align="center" nowrap><?php echo Format::datetime($row['effective_date']); ?></td>
+            <td align="center" nowrap><?php echo Format::datetime($T['effective_date']); ?></td>
             <td><?php echo $status; ?></td>
-            <td><a <?php if ($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?>
-                href="tickets.php?id=<?php echo $T['ticket_id']; ?>"><span class="truncate"
-                style="max-width: 290px"><?php echo $subject; ?></span></a>
+            <td><a class="truncate <?php if ($flag) { ?> Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket<?php } ?>"
+                style="max-width: 230px;"
+                href="tickets.php?id=<?php echo $T['ticket_id']; ?>"><?php echo $subject; ?></a>
                  <?php
                     if ($threadcount > 1) { ?>
-                        <span class="pull-right faded-more"><i class="icon-comments-alt"></i>
-                        <small><?php echo $threadcount; ?></small>
+                            <span class="pull-right faded-more"><i class="icon-comments-alt"></i>
+                            <small><?php echo $threadcount; ?></small></span>
 <?php               }
-                    if ($row['attachments'])
+                    if ($T['attachments'])
                         echo '<i class="small icon-paperclip icon-flip-horizontal"></i>';
-                    if ($row['collaborators'])
+                    if ($T['collaborators'])
                         echo '<i class="icon-group faded-more"></i>';
                 ?>
-            </td>
+            </span></td>
             <?php
             if ($user) {
                 $dept = Dept::getLocalById($T['dept_id'], 'name', $T['dept__name']); ?>
-            <td><span class="truncate" style="max-wdith:150px"><?php
+            <td><span class="truncate" style="max-wdith:125px"><?php
                 echo Format::htmlchars($dept); ?></span></td>
-            <td><span class="truncate" style="max-width:150px"><?php
+            <td><span class="truncate" style="max-width:125px"><?php
                 echo Format::htmlchars($assigned); ?></span></td>
             <?php
             } else { ?>
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index ca01e03ddb0383ba6451abeeffcf2a85dba5f0b5..edb325b288a66eab97a80b29283d15ddff8fca98 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -16,6 +16,20 @@ unset($args['a']);
 
 $refresh_url = $path . '?' . http_build_query($args);
 
+$sort_options = array(
+    'priority,updated' =>   __('Priority + Most Recently Updated'),
+    'updated' =>            __('Most Recently Updated'),
+    'priority,created' =>   __('Priority + Most Recently Created'),
+    'due' =>                __('Due Soon'),
+    'priority,due' =>       __('Priority + Due Soon'),
+    'number' =>             __('Ticket Number'),
+    'answered' =>           __('Most Recently Answered'),
+    'closed' =>             __('Most Recently Closed'),
+    'hot' =>                __('Longest Thread'),
+    'relevance' =>          __('Relevance'),
+);
+$use_subquery = true;
+
 $queue_name = strtolower($_GET['status'] ?: $_GET['a']); //Status is overloaded
 switch ($queue_name) {
 case 'closed':
@@ -23,23 +37,32 @@ case 'closed':
     $results_type=__('Closed Tickets');
     $showassigned=true; //closed by.
     $tickets->values('staff__firstname', 'staff__lastname', 'team__name', 'team_id');
+    $queue_sort_options = array('closed', 'priority,due', 'due',
+        'priority,updated', 'priority,created', 'answered', 'number', 'hot');
     break;
 case 'overdue':
     $status='open';
     $results_type=__('Overdue Tickets');
     $tickets->filter(array('isoverdue'=>1));
+    $queue_sort_options = array('priority,due', 'due', 'priority,updated',
+        'updated', 'answered', 'priority,created', 'number', 'hot');
     break;
 case 'assigned':
     $status='open';
     $staffId=$thisstaff->getId();
     $results_type=__('My Tickets');
     $tickets->filter(array('staff_id'=>$thisstaff->getId()));
+    $queue_sort_options = array('updated', 'priority,updated',
+        'priority,created', 'priority,due', 'due', 'answered', 'number',
+        'hot');
     break;
 case 'answered':
     $status='open';
     $showanswered=true;
     $results_type=__('Answered Tickets');
     $tickets->filter(array('isanswered'=>1));
+    $queue_sort_options = array('answered', 'priority,updated', 'updated',
+        'priority,created', 'priority,due', 'due', 'number', 'hot');
     break;
 default:
 case 'search':
@@ -55,7 +78,9 @@ case 'search':
         else {
             $tickets = $tickets->filter(Q::any(array(
                 'number__startswith' => $_REQUEST['query'],
+                'user__name__contains' => $_REQUEST['query'],
                 'user__emails__address__contains' => $_REQUEST['query'],
+                'user__org__name__contains' => $_REQUEST['query'],
             )));
         }
         break;
@@ -66,7 +91,25 @@ case 'search':
         $tickets = $search->mangleQuerySet($tickets, $form);
         $view_all_tickets = $thisstaff->getRole()->hasPerm(SearchBackend::PERM_EVERYTHING);
         $results_type=__('Advanced Search')
-            . '<a class="action-button" href="?clear_filter"><i class="icon-ban-circle"></i> <em>' . __('clear') . '</em></a>';
+            . '<a class="action-button" href="?clear_filter"><i style="top:0" class="icon-ban-circle"></i> <em>' . __('clear') . '</em></a>';
+        $queue_sort_options = array('priority,updated', 'priority,created',
+            'priority,due', 'due', 'updated', 'answered',
+            'closed', 'number', 'hot');
+        $has_relevance = false;
+        foreach ($tickets->getSortFields() as $sf) {
+            if ($sf instanceof SqlCode && $sf->code == '`relevance`') {
+                $has_relevance = true;
+                break;
+            }
+        }
+        if ($has_relevance) {
+            $use_subquery = false;
+            array_unshift($queue_sort_options, 'relevance');
+        }
+        elseif ($_SESSION[$queue_sort_key] == 'relevance') {
+            unset($_SESSION[$queue_sort_key]);
+        }
+
         break;
     }
     // Fall-through and show open tickets
@@ -80,6 +123,9 @@ case 'open':
         $tickets->filter(Q::any(array('staff_id'=>0, 'team_id'=>0)));
     else
         $tickets->values('staff__firstname', 'staff__lastname', 'team__name');
+    $queue_sort_options = array('priority,updated', 'updated',
+        'priority,due', 'due', 'priority,created', 'answered', 'number',
+        'hot');
     break;
 }
 
@@ -97,45 +143,55 @@ if ($status)
 // ------------------------------------------------------------
 if (!$view_all_tickets) {
     // -- Open and assigned to me
+    $assigned = Q::any(array(
+        'staff_id' => $thisstaff->getId(),
+    ));
+    // -- Open and assigned to a team of mine
+    if ($teams = array_filter($thisstaff->getTeams()))
+        $assigned->add(array('team_id__in' => $teams));
+
     $visibility = array(
-        new Q(array('status__state'=>'open', 'staff_id' => $thisstaff->getId()))
+        new Q(array('status__state'=>'open', $assigned))
     );
     // -- Routed to a department of mine
     if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
         $visibility[] = new Q(array('dept_id__in' => $depts));
-    // -- Open and assigned to a team of mine
-    if (($teams = $thisstaff->getTeams()) && count(array_filter($teams)))
-        $visibility[] = new Q(array(
-            'team_id__in' => array_filter($teams), 'status__state'=>'open'
-        ));
+
     $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'),
-));
-
-// 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');
+// TODO :: Apply requested quick filter
 
-// 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);
 
 // Apply requested sorting
 $queue_sort_key = sprintf(':Q:%s:sort', $queue_name);
 
-if (isset($_GET['sort']))
+if (isset($_GET['sort'])) {
     $_SESSION[$queue_sort_key] = $_GET['sort'];
+}
+elseif (!isset($_SESSION[$queue_sort_key])) {
+    $_SESSION[$queue_sort_key] = $queue_sort_options[0];
+}
+
 switch ($_SESSION[$queue_sort_key]) {
 case 'number':
     $tickets->extra(array(
         'order_by'=>array(SqlExpression::times(new SqlField('number'), 1))
     ));
     break;
+
+case 'priority,created':
+    $tickets->order_by('cdata__:priority__priority_urgency');
+    // Fall through to columns for `created`
 case 'created':
+    $date_header = __('Date Created');
+    $date_col = 'created';
+    $tickets->values('created');
     $tickets->order_by('-created');
     break;
 
@@ -146,26 +202,77 @@ case 'due':
     $date_header = __('Due Date');
     $date_col = 'est_duedate';
     $tickets->values('est_duedate');
-    $tickets->filter(array('est_duedate__isnull'=>false));
-    $tickets->order_by('est_duedate');
+    $tickets->order_by(SqlFunction::COALESCE(new SqlField('est_duedate'), 'zzz'));
+    break;
+
+case 'closed':
+    $date_header = __('Date Closed');
+    $date_col = 'closed';
+    $tickets->values('closed');
+    $tickets->order_by('-closed');
+    break;
+
+case 'answered':
+    $date_header = __('Last Response');
+    $date_col = 'lastresponse';
+    $date_fallback = '<em class="faded">'.__('unanswered').'</em>';
+    $tickets->order_by('-lastresponse');
+    $tickets->values('lastresponse');
+    break;
+
+case 'hot':
+    $tickets->order_by('-thread_count');
+    $tickets->annotate(array(
+        'thread_count' => SqlAggregate::COUNT('thread__entries'),
+    ));
+    break;
+
+case 'relevance':
+    $tickets->order_by(new SqlCode('relevance'));
     break;
 
 default:
+case 'priority,updated':
+    $tickets->order_by('cdata__:priority__priority_urgency');
+    // Fall through for columns defined for `updated`
 case 'updated':
-    $tickets->order_by('cdata__:priority__priority_urgency', '-lastupdate');
+    $date_header = __('Last Updated');
+    $date_col = 'lastupdate';
+    $tickets->order_by('-lastupdate');
     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);
+
+// Rewrite $tickets to use a nested query, which will include the LIMIT part
+// in order to speed the result
+//
+// ATM, advanced search with keywords doesn't support the subquery approach
+if ($use_subquery) {
+    $orig_tickets = clone $tickets;
+    $tickets2 = TicketModel::objects();
+    $tickets2->values = $tickets->values;
+    $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;
+$_SESSION[':Q:tickets'] = $orig_tickets;
 
 ?>
 
@@ -199,14 +306,12 @@ $_SESSION[':Q:tickets'] = $tickets;
         <div class="pull-right flush-right">
             <span style="display:inline-block">
                 <span style="vertical-align: baseline">Sort:</span>
-            <select name="sort" onchange="javascript:addSearchParam('sort', $(this).val());">
-<?php foreach (array(
-    'updated' =>    __('Most Recently Updated'),
-    'created' =>    __('Most Recently Created'),
-    'due' =>        __('Due Soon'),
-    'priority,due' => __('Priority + Due Soon'),
-    'number' =>     __('Ticket Number'),
-) as $mode => $desc) { ?>
+            <select name="sort" onchange="javascript: $.pjax({
+                url:'?' + addSearchParam('sort', $(this).val()),
+                timeout: 2000,
+                container: '#pjax-container'});">
+<?php foreach ($queue_sort_options as $mode) {
+    $desc = $sort_options[$mode]; ?>
             <option value="<?php echo $mode; ?>" <?php if ($mode == $_SESSION[$queue_sort_key]) echo 'selected="selected"'; ?>><?php echo $desc; ?></option>
 <?php } ?>
             </select>
@@ -230,7 +335,7 @@ $_SESSION[':Q:tickets'] = $tickets;
  <input type="hidden" name="do" id="action" value="" >
  <input type="hidden" name="status" value="<?php echo
  Format::htmlchars($_REQUEST['status'], true); ?>" >
- <table class="list fixed" border="0" cellspacing="1" cellpadding="2" width="940">
+ <table class="list" border="0" cellspacing="1" cellpadding="2" width="940">
     <thead>
         <tr>
             <?php if ($thisstaff->canManageTickets()) { ?>
@@ -239,7 +344,7 @@ $_SESSION[':Q:tickets'] = $tickets;
 	        <th width="70">
                 <?php echo __('Ticket'); ?></th>
 	        <th width="100">
-                <?php echo $date_header ?: __('Date'); ?></th>
+                <?php echo $date_header ?: __('Date Created'); ?></th>
 	        <th width="280">
                 <?php echo __('Subject'); ?></th>
             <th width="170">
@@ -291,17 +396,14 @@ $_SESSION[':Q:tickets'] = $tickets;
                     $flag='overdue';
 
                 $lc='';
-                $dept = Dept::getLocalById($T['dept_id'], 'name', $T['dept__name']);
-                if($showassigned) {
-                    if($T['staff_id'])
-                        $lc=sprintf('<span class="Icon staffAssigned truncate">%s</span>',(string) new PersonsName($T['staff__firstname'].' '.$T['staff__lastname']));
-                    elseif($T['team_id'])
-                        $lc=sprintf('<span class="Icon teamAssigned">%s</span>',
-                            Team::getLocalById($T['team_id'], 'name', $T['team__name']));
-                    else
-                        $lc=' ';
-                }else{
-                    $lc='<span class="truncate">'.Format::htmlchars($dept).'</span>';
+                if ($showassigned) {
+                    if ($T['staff_id'])
+                        $lc = new PersonsName($T['staff__firstname'].' '.$T['staff__lastname']);
+                    elseif ($T['team_id'])
+                        $lc = Team::getLocalById($T['team_id'], 'name', $T['team__name']);
+                }
+                else {
+                    $lc = Dept::getLocalById($T['dept_id'], 'name', $T['dept__name']);
                 }
                 $tid=$T['number'];
                 $subject = $subject_field->display($subject_field->to_php($T['cdata__subject']));
@@ -328,25 +430,27 @@ $_SESSION[':Q:tickets'] = $tickets;
                     href="tickets.php?id=<?php echo $T['ticket_id']; ?>"
                     data-preview="#tickets/<?php echo $T['ticket_id']; ?>/preview"
                     ><?php echo $tid; ?></a></td>
-                <td align="center" nowrap><?php echo Format::datetime($T[$date_col ?: 'lastupdate']); ?></td>
+                <td align="center" nowrap><?php echo Format::datetime($T[$date_col ?: 'lastupdate']) ?: $date_fallback; ?></td>
                 <td><a <?php if ($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?>
-                    style="max-width: 80%; max-width: calc(100% - 86px);"
+                    style="max-width: 210px;"
                     href="tickets.php?id=<?php echo $T['ticket_id']; ?>"><span
                     class="truncate"><?php echo $subject; ?></span></a>
-                     <?php
-                        if ($threadcount>1)
-                            echo "<small>($threadcount)</small>&nbsp;".'<i
-                                class="icon-fixed-width icon-comments-alt"></i>&nbsp;';
-                        if ($T['collab_count'])
-                            echo '<i class="icon-fixed-width icon-group faded"></i>&nbsp;';
-                        if ($T['attachment_count'])
-                            echo '<i class="icon-fixed-width icon-paperclip"></i>&nbsp;';
-                    ?>
+<?php               if ($T['attachment_count'])
+                        echo '<i class="small icon-paperclip icon-flip-horizontal"></i>';
+                    if ($threadcount > 1) { ?>
+                        <span class="pull-right faded-more"><i class="icon-comments-alt"></i>
+                            <small><?php echo $threadcount; ?></small>
+                        </span>
+                    <?php } ?>
                 </td>
-                <td nowrap><span class="truncate"><?php
+                <td nowrap><div><?php
+                    if ($T['collab_count'])
+                        echo '<span class="pull-right faded-more"><i class="icon-group"></i></span>';
+                    ?><span class="truncate" style="max-width:<?php
+                        echo $T['collab_count'] ? '150px' : '170px'; ?>"><?php
                     $un = new PersonsName($T['user__name']);
                         echo Format::htmlchars($un);
-                ?></td>
+                    ?></span></div></td>
                 <?php
                 if($search && !$status){
                     $displaystatus=TicketStatus::getLocalById($T['status_id'], 'value', $T['status__name']);
@@ -359,7 +463,7 @@ $_SESSION[':Q:tickets'] = $tickets;
                 <?php
                 }
                 ?>
-                <td nowrap>&nbsp;<?php echo $lc; ?></td>
+                <td nowrap>&nbsp;<?php echo Format::htmlchars($lc); ?></td>
             </tr>
             <?php
             } //end of foreach
diff --git a/scp/css/scp.css b/scp/css/scp.css
index 68188bee7044962c36c077f62de59da1250092e1..c64d284d8fdf27bf2676339fd90845872d03e918 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -58,6 +58,17 @@ div#header a {
 .faded {
     color:#666;
 }
+.faded-more {
+    color: #aaa;
+    color: rgba(0,0,0,0.4);
+}
+
+.small[class^="icon-"],
+.small[class*=" icon-"] {
+    vertical-align: baseline;
+    padding-left: 2px;
+    font-size: 80%;
+}
 
 .strike { text-decoration:line-through; color:red; }
 
@@ -377,6 +388,7 @@ a.lists { background:url(../images/icons/icon-list.png); background-size: 16px 1
     background-repeat: no-repeat;
     min-height: 16px;
     display: inline-block;
+    vertical-align: middle;
 }
 
 
diff --git a/scp/js/scp.js b/scp/js/scp.js
index 0a0e577a809f840360570946e65bcae3bb371e76..79d14e3da1ecd8c5f06d16ad2f0630d890666ba7 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -901,5 +901,5 @@ function addSearchParam(key, value) {
     if(i<0) {kvp[kvp.length] = [key,value].join('=');}
 
     //this will reload the page, it's likely better to store this until finished
-    document.location.search = kvp.join('&');
+    return kvp.join('&');
 }