How can I use the MySQL FIELD() function within a SelectQuery object in Views? I want to use the MySQL FIELD() function to alter a query so that it orders a particular field on a particular order of keys.

The keys for this 'select' field are: active, under_contract, sold

I want to sort the View so that all of my results are sorted first by node.created DESC (this is simple, of course) and then push all sold nodes to the very bottom of the result.

I tried doing this first in hook_views_post_execute():

function mymodule_views_post_execute(&amp;$view) {
  if ($view-&gt;name == 'my_view') {
    usort($view-&gt;result, function($a, $b) {
      return ($a-&gt;field_field_status[0]['raw']['value'] == 'sold') ? 1 : -1;
    });
  }
}


but quickly discovered that, since my view only shows 25 results per page, this only pushes sold nodes to the bottom of each page.

Next, I tried to use hook_views_query_alter() to add the awesome MySQL FIELD() function that I just discovered – which works to achieve my goal perfectly in MySQL - but can't be added (at least as I'm discovering) to a SelectQuery object, which Views uses to run the query:

function mymodule_views_query_alter(&amp;$view, &amp;$query) {
  if ($view-&gt;name == 'my_view') {
    $query-&gt;orderby[0] = array(
      'field' =&gt; " FIELD(field_data_field_status.field_status_value, 'sold') ",
      'direction' =&gt; 'DESC',
  );
  }
}


How can I add a FIELD() orderby function to this query? Is there another method to push a particular filter value to the bottom of the result queue?
I got this working! I couldn't find any way to get the orderBy working in hook_views_query_alter(), so I tried to do this in the raw hook_query_alter(). In my particular situation, I couldn't get any result when I filtered against the table that Views had already joined with (I can't explain why) and so I added my own join. Voila, it works.

function mymodule_query_alter($query) {
  if ($query-&gt;hasTag('my_view_id')) {
    // Remove the current sort order. 
    $order =&amp; $query-&gt;getOrderBy();
    $order = array();

    // Join with the table that we need, giving it a custom alias.
    $query-&gt;join('field_data_field_listing_status', 'custom_status', 'custom_status.entity_id = node.nid');

    // Add our cool FIELD() function to push all 'sold' nodes to the very back of the list.
    $query-&gt;orderBy("FIELD(custom_status.field_listing_status_value, 'sold')", 'ASC');

    // Add any other ordering that we need...
    $query-&gt;orderBy('node_created', 'DESC');
  }
}