diff --git a/CRM/Case/BAO/Case.php b/CRM/Case/BAO/Case.php
index 3fa0e9113c6d3c62491c1c7092f5f005c30e7b56..222860016a0125dbbdd91beeb93e281a0613b555 100644
--- a/CRM/Case/BAO/Case.php
+++ b/CRM/Case/BAO/Case.php
@@ -429,121 +429,60 @@ WHERE cc.contact_id = %1 AND civicrm_case_type.name = '{$caseType}'";
       'civicrm_phone.phone as phone',
       'civicrm_contact.contact_type as contact_type',
       'civicrm_contact.contact_sub_type as contact_sub_type',
-      't_act.activity_type_id',
-      'c_type.title as case_type',
+      't_act.activity_type_id as activity_type_id',
       'civicrm_case.case_type_id as case_type_id',
-      'cov_status.label as case_status',
-      'cov_status.label as case_status_name',
-      't_act.status_id',
+      'civicrm_case.status_id as case_status_id',
+      't_act.status_id as status_id',
       'civicrm_case.start_date as case_start_date',
       'case_relation_type.label_b_a as case_role',
+      't_act.activity_date_time as activity_date_time',
+      't_act.id as activity_id',
     );
 
-    if ($type == 'upcoming') {
-      $selectClauses = array_merge($selectClauses, array(
-        't_act.desired_date as case_scheduled_activity_date',
-        't_act.id as case_scheduled_activity_id',
-        't_act.act_type_name as case_scheduled_activity_type_name',
-        't_act.act_type AS case_scheduled_activity_type',
-      ));
-    }
-    elseif ($type == 'recent') {
-      $selectClauses = array_merge($selectClauses, array(
-        't_act.desired_date as case_recent_activity_date',
-        't_act.id as case_recent_activity_id',
-        't_act.act_type_name as case_recent_activity_type_name',
-        't_act.act_type AS case_recent_activity_type',
-      ));
-    }
-    elseif ($type == 'any') {
-      $selectClauses = array_merge($selectClauses, array(
-        't_act.desired_date as case_activity_date',
-        't_act.id as case_activity_id',
-        't_act.act_type_name as case_activity_type_name',
-        't_act.act_type AS case_activity_type',
-      ));
-    }
-
     $query = CRM_Contact_BAO_Query::appendAnyValueToSelect($selectClauses, 'case_id');
 
-    $query .= " FROM civicrm_case
-                  INNER JOIN civicrm_case_contact ON civicrm_case.id = civicrm_case_contact.case_id
-                  INNER JOIN civicrm_contact ON civicrm_case_contact.contact_id = civicrm_contact.id ";
-
-    if ($type == 'upcoming') {
-      // This gets the earliest activity per case that's scheduled within 14 days from now.
-      // Note we have an inner select to get the min activity id in order to remove duplicates in case there are two with the same datetime.
-      // In this case we don't really care which one, so min(id) works.
-      // optimized in CRM-11837
-      $query .= " INNER JOIN
-(
-  SELECT case_id, act.id, activity_date_time AS desired_date, activity_type_id, status_id, aov.name AS act_type_name, aov.label AS act_type
-  FROM (
-    SELECT *
-    FROM (
-      SELECT *
-      FROM civicrm_view_case_activity_upcoming
-      ORDER BY activity_date_time ASC, id ASC
-      ) AS upcomingOrdered
-    ) AS act
-  LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
-  LEFT JOIN civicrm_option_value aov ON ( aov.option_group_id = aog.id AND aov.value = act.activity_type_id )
-) AS t_act
-";
-    }
-    elseif ($type == 'recent') {
-      // Similarly, the most recent activity in the past 14 days, and exclude scheduled.
-      //improve query performance - CRM-10598
-      $query .= " INNER JOIN
-(
-  SELECT case_id, act.id, activity_date_time AS desired_date, activity_type_id, status_id, aov.name AS act_type_name, aov.label AS act_type
-  FROM (
-    SELECT *
-    FROM (
-      SELECT *
-      FROM civicrm_view_case_activity_recent
-      ORDER BY activity_date_time DESC, id ASC
-      ) AS recentOrdered
-    ) AS act
-LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
-  LEFT JOIN civicrm_option_value aov ON ( aov.option_group_id = aog.id AND aov.value = act.activity_type_id )
-) AS t_act ";
-    }
-    elseif ($type == 'any') {
-      $query .= " LEFT JOIN
-(
-  SELECT ca4.case_id, act4.id AS id, act4.activity_date_time AS desired_date, act4.activity_type_id, act4.status_id, aov.name AS act_type_name, aov.label AS act_type
-  FROM civicrm_activity act4
-  LEFT JOIN civicrm_case_activity ca4
-    ON ca4.activity_id = act4.id
-    AND act4.is_current_revision = 1
-  LEFT JOIN civicrm_option_group aog
-    ON aog.name='activity_type'
-  LEFT JOIN civicrm_option_value aov
-    ON aov.option_group_id = aog.id
-    AND aov.value = act4.activity_type_id
-) AS t_act";
-    }
-
-    $query .= "
-        ON t_act.case_id = civicrm_case.id
- LEFT JOIN civicrm_phone ON (civicrm_phone.contact_id = civicrm_contact.id AND civicrm_phone.is_primary=1)
- LEFT JOIN civicrm_relationship case_relationship
- ON ( case_relationship.contact_id_a = civicrm_case_contact.contact_id AND case_relationship.contact_id_b = {$userID} AND case_relationship.is_active AND case_relationship.case_id = civicrm_case.id )
- LEFT JOIN civicrm_relationship_type case_relation_type
- ON ( case_relation_type.id = case_relationship.relationship_type_id
-      AND case_relation_type.id = case_relationship.relationship_type_id )
-
- LEFT JOIN civicrm_case_type c_type
- ON civicrm_case.case_type_id = c_type.id
-
- LEFT JOIN civicrm_option_group cog_status
- ON cog_status.name = 'case_status'
-
- LEFT JOIN civicrm_option_value cov_status
- ON ( civicrm_case.status_id = cov_status.value
-      AND cog_status.id = cov_status.option_group_id )
-";
+    $query .= <<<HERESQL
+      FROM civicrm_case
+        INNER JOIN civicrm_case_contact ON civicrm_case.id = civicrm_case_contact.case_id
+        INNER JOIN civicrm_contact ON civicrm_case_contact.contact_id = civicrm_contact.id
+HERESQL;
+
+    switch ($type) {
+      case 'upcoming':
+      case 'recent':
+        // civicrm_view_case_activity_upcoming and
+        // civicrm_view_case_activity_recent are views that show the next
+        // scheduled and most recent not-scheduled activity on each case,
+        // respectively.
+        $query .= <<<HERESQL
+        INNER JOIN civicrm_view_case_activity_$type t_act
+          ON t_act.case_id = civicrm_case.id
+HERESQL;
+        break;
+
+      case 'any':
+        $query .= <<<HERESQL
+        LEFT JOIN civicrm_case_activity ca4
+          ON civicrm_case.id = ca4.case_id
+        LEFT JOIN civicrm_activity t_act
+          ON t_act.id = ca4.activity_id
+          AND t_act.is_current_revision = 1
+HERESQL;
+    }
+
+    $query .= <<<HERESQL
+        LEFT JOIN civicrm_phone
+          ON civicrm_phone.contact_id = civicrm_contact.id
+            AND civicrm_phone.is_primary = 1
+        LEFT JOIN civicrm_relationship case_relationship
+          ON case_relationship.contact_id_a = civicrm_case_contact.contact_id
+            AND case_relationship.contact_id_b = {$userID}
+            AND case_relationship.is_active
+            AND case_relationship.case_id = civicrm_case.id
+        LEFT JOIN civicrm_relationship_type case_relation_type
+          ON case_relation_type.id = case_relationship.relationship_type_id
+            AND case_relation_type.id = case_relationship.relationship_type_id
+HERESQL;
 
     if ($condition) {
       // CRM-8749 backwards compatibility - callers of this function expect to start $condition with "AND"
@@ -551,20 +490,7 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
     }
     $query .= " GROUP BY case_id ";
 
-    if ($order) {
-      $query .= $order;
-    }
-    else {
-      if ($type == 'upcoming') {
-        $query .= " ORDER BY case_scheduled_activity_date ASC ";
-      }
-      elseif ($type == 'recent') {
-        $query .= " ORDER BY case_recent_activity_date ASC ";
-      }
-      elseif ($type == 'any') {
-        $query .= " ORDER BY case_activity_date ASC ";
-      }
-    }
+    $query .= ($order) ?: ' ORDER BY activity_date_time ASC';
 
     if ($limit) {
       $query .= $limit;
@@ -601,20 +527,6 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
     $type = CRM_Utils_Array::value('type', $params, 'upcoming');
     $userID = CRM_Core_Session::singleton()->get('userID');
 
-    $caseActivityTypeColumn = 'case_activity_type_name';
-    $caseActivityDateColumn = 'case_activity_date';
-    $caseActivityIDColumn = 'case_activity_id';
-    if ($type == 'upcoming') {
-      $caseActivityDateColumn = 'case_scheduled_activity_date';
-      $caseActivityTypeColumn = 'case_scheduled_activity_type';
-      $caseActivityIDColumn = 'case_scheduled_activity_id';
-    }
-    elseif ($type == 'recent') {
-      $caseActivityDateColumn = 'case_recent_activity_date';
-      $caseActivityTypeColumn = 'case_recent_activity_type';
-      $caseActivityIDColumn = 'case_recent_activity_id';
-    }
-
     // validate access for all cases.
     if ($allCases && !CRM_Core_Permission::check('access all cases and activities')) {
       $allCases = FALSE;
@@ -654,7 +566,7 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
     $order = NULL;
     if (!empty($params['sortBy'])) {
       if (strstr($params['sortBy'], 'date ')) {
-        $params['sortBy'] = str_replace('date', $caseActivityDateColumn, $params['sortBy']);
+        $params['sortBy'] = str_replace('date', 'activity_date_time', $params['sortBy']);
       }
       $order = "ORDER BY " . $params['sortBy'];
     }
@@ -662,8 +574,6 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
     $query = self::getCaseActivityQuery($type, $userID, $condition, $limit, $order);
     $result = CRM_Core_DAO::executeQuery($query);
 
-    $caseStatus = CRM_Core_OptionGroup::values('case_status', FALSE, FALSE, FALSE, " AND v.name = 'Urgent' ");
-
     // we're going to use the usual actions, so doesn't make sense to duplicate definitions
     $actions = CRM_Case_Selector_Search::links();
 
@@ -679,7 +589,12 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
     }
     $mask = CRM_Core_Action::mask($permissions);
 
+    // Pseudoconstants to populate labels
+    $caseStatuses = CRM_Case_PseudoConstant::caseStatus('label', FALSE);
     $caseTypes = CRM_Case_PseudoConstant::caseType('name');
+    $caseTypeTitles = CRM_Case_PseudoConstant::caseType('title', FALSE);
+    $activityTypeLabels = CRM_Activity_BAO_Activity::buildOptions('activity_type_id');
+
     foreach ($result->fetchAll() as $case) {
       $key = $case['case_id'];
       $casesList[$key] = array();
@@ -701,30 +616,31 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
         $case['case_id']
       );
       $casesList[$key]['subject'] = $case['case_subject'];
-      $casesList[$key]['case_status'] = in_array($case['case_status'], $caseStatus) ? sprintf('<strong>%s</strong>', strtoupper($case['case_status'])) : $case['case_status'];
-      $casesList[$key]['case_type'] = $case['case_type'];
+      $casesList[$key]['case_status'] = CRM_Utils_Array::value($case['case_status_id'], $caseStatuses);
+      if ($case['case_status_id'] == CRM_Case_PseudoConstant::getKey('CRM_Case_BAO_Case', 'case_status_id', 'Urgent')) {
+        $casesList[$key]['case_status'] = sprintf('<strong>%s</strong>', strtoupper($casesList[$key]['case_status']));
+      }
+      $casesList[$key]['case_type'] = CRM_Utils_Array::value($case['case_type_id'], $caseTypeTitles);
       $casesList[$key]['case_role'] = CRM_Utils_Array::value('case_role', $case, '---');
       $casesList[$key]['manager'] = self::getCaseManagerContact($caseTypes[$case['case_type_id']], $case['case_id']);
 
-      $casesList[$key]['date'] = $case[$caseActivityTypeColumn];
-      if (($actId = CRM_Utils_Array::value('case_scheduled_activity_id', $case)) ||
-        ($actId = CRM_Utils_Array::value('case_recent_activity_id', $case))
-      ) {
+      $casesList[$key]['date'] = CRM_Utils_Array::value($case['activity_type_id'], $activityTypeLabels);
+      if ($actId = CRM_Utils_Array::value('activity_id', $case)) {
         if (self::checkPermission($actId, 'view', $case['activity_type_id'], $userID)) {
           if ($type == 'recent') {
             $casesList[$key]['date'] = sprintf('<a class="action-item crm-hover-button" href="%s" title="%s">%s</a>',
-              CRM_Utils_System::url('civicrm/case/activity/view', array('reset' => 1, 'cid' => $case['contact_id'], 'aid' => $case[$caseActivityIDColumn])),
+              CRM_Utils_System::url('civicrm/case/activity/view', array('reset' => 1, 'cid' => $case['contact_id'], 'aid' => $case['activity_id'])),
               ts('View activity'),
-              $case[$caseActivityTypeColumn]
+              CRM_Utils_Array::value($case['activity_type_id'], $activityTypeLabels)
             );
           }
           else {
-            $status = CRM_Utils_Date::overdue($case[$caseActivityDateColumn]) ? 'status-overdue' : 'status-scheduled';
+            $status = CRM_Utils_Date::overdue($case['activity_date_time']) ? 'status-overdue' : 'status-scheduled';
             $casesList[$key]['date'] = sprintf('<a class="crm-popup %s" href="%s" title="%s">%s</a> &nbsp;&nbsp;',
              $status,
-              CRM_Utils_System::url('civicrm/case/activity/view', array('reset' => 1, 'cid' => $case['contact_id'], 'aid' => $case[$caseActivityIDColumn])),
+              CRM_Utils_System::url('civicrm/case/activity/view', array('reset' => 1, 'cid' => $case['contact_id'], 'aid' => $case['activity_id'])),
               ts('View activity'),
-              $case[$caseActivityTypeColumn]
+              CRM_Utils_Array::value($case['activity_type_id'], $activityTypeLabels)
             );
           }
         }
@@ -735,7 +651,7 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
           );
         }
       }
-      $casesList[$key]['date'] .= "<br/>" . CRM_Utils_Date::customFormat($case[$caseActivityDateColumn]);
+      $casesList[$key]['date'] .= "<br/>" . CRM_Utils_Date::customFormat($case['activity_date_time']);
       $casesList[$key]['links'] = CRM_Core_Action::formLink($actions['primaryActions'], $mask,
         array(
           'id' => $case['case_id'],
@@ -1627,18 +1543,19 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c
  AND civicrm_case.is_deleted     = {$cases['case_deleted']}";
 
     $query = self::getCaseActivityQuery($type, $userID, $condition);
+    $activityTypes = CRM_Activity_BAO_Activity::buildOptions('activity_type_id');
 
     $res = CRM_Core_DAO::executeQuery($query);
 
     $activityInfo = array();
     while ($res->fetch()) {
       if ($type == 'upcoming') {
-        $activityInfo[$res->case_id]['date'] = $res->case_scheduled_activity_date;
-        $activityInfo[$res->case_id]['type'] = $res->case_scheduled_activity_type;
+        $activityInfo[$res->case_id]['date'] = $res->activity_date_time;
+        $activityInfo[$res->case_id]['type'] = CRM_Utils_Array::value($res->activity_type_id, $activityTypes);
       }
       else {
-        $activityInfo[$res->case_id]['date'] = $res->case_recent_activity_date;
-        $activityInfo[$res->case_id]['type'] = $res->case_recent_activity_type;
+        $activityInfo[$res->case_id]['date'] = $res->activity_date_time;
+        $activityInfo[$res->case_id]['type'] = CRM_Utils_Array::value($res->activity_type_id, $activityTypes);
       }
     }
 
@@ -3055,8 +2972,8 @@ WHERE id IN (' . implode(',', $copiedActivityIds) . ')';
  AS SELECT ca.case_id, a.id, a.activity_date_time, a.status_id, a.activity_type_id
  FROM civicrm_case_activity ca
  INNER JOIN civicrm_activity a ON ca.activity_id=a.id
- WHERE a.activity_date_time =
-(SELECT b.activity_date_time FROM civicrm_case_activity bca
+ WHERE a.id =
+(SELECT b.id FROM civicrm_case_activity bca
  INNER JOIN civicrm_activity b ON bca.activity_id=b.id
  WHERE b.activity_date_time <= DATE_ADD( NOW(), INTERVAL 14 DAY )
  AND b.is_current_revision = 1 AND b.is_deleted=0 AND b.status_id = $scheduled_id
@@ -3068,8 +2985,8 @@ WHERE id IN (' . implode(',', $copiedActivityIds) . ')';
  AS SELECT ca.case_id, a.id, a.activity_date_time, a.status_id, a.activity_type_id
  FROM civicrm_case_activity ca
  INNER JOIN civicrm_activity a ON ca.activity_id=a.id
- WHERE a.activity_date_time =
-(SELECT b.activity_date_time FROM civicrm_case_activity bca
+ WHERE a.id =
+(SELECT b.id FROM civicrm_case_activity bca
  INNER JOIN civicrm_activity b ON bca.activity_id=b.id
  WHERE b.activity_date_time >= DATE_SUB( NOW(), INTERVAL 14 DAY )
  AND b.is_current_revision = 1 AND b.is_deleted=0 AND b.status_id <> $scheduled_id
diff --git a/tests/phpunit/CRM/Case/BAO/CaseTest.php b/tests/phpunit/CRM/Case/BAO/CaseTest.php
index 7c8f1ed47f8ba97b734e660d07bef8e30c7a9662..0d1c270d5fb6a7331d01bb15e80f6daa3751c761 100644
--- a/tests/phpunit/CRM/Case/BAO/CaseTest.php
+++ b/tests/phpunit/CRM/Case/BAO/CaseTest.php
@@ -31,6 +31,28 @@ class CRM_Case_BAO_CaseTest extends CiviUnitTestCase {
     CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
   }
 
+  /**
+   * Make sure that the latest case activity works accurately.
+   */
+  public function testCaseActivity() {
+    $userID = $this->createLoggedInUser();
+
+    $addTimeline = civicrm_api3('Case', 'addtimeline', [
+      'case_id' => 1,
+      'timeline' => "standard_timeline",
+    ]);
+
+    $query = CRM_Case_BAO_Case::getCaseActivityQuery('recent', $userID, ' civicrm_case.id IN( 1 )');
+    $res = CRM_Core_DAO::executeQuery($query);
+    $openCaseType = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Open Case');
+    while ($res->fetch()) {
+      $message = 'Failed asserting that the case activity query has a activity_type_id property:';
+      $this->assertObjectHasAttribute('activity_type_id', $res, $message . PHP_EOL . print_r($res, TRUE));
+      $message = 'Failed asserting that the latest activity from Case ID 1 was "Open Case":';
+      $this->assertEquals($openCaseType, $res->activity_type_id, $message . PHP_EOL . print_r($res, TRUE));
+    }
+  }
+
   protected function tearDown() {
     parent::tearDown();
     $this->quickCleanup($this->tablesToTruncate, TRUE);