The View field module allows you to expose field tables as base tables to views. This differs from Views default behavior in that the base table is the field table and not an entity to which the field data is then loaded from. For example when selecting node as a base table you can then add fields, but the primary (base table) in the query is still node which depending on your data can screw up the aggregate functions (aka a many-to-one relationship of some fields to the node).
Views field allows you direct access to the field tables which means aggregate functions work properly. Additionally if you need to do "interesting" joins to other field tables you can control them completely using the following.
/**
* Implements hook_views_data_alter().
*/
function mymodule_views_data_alter(&$data) {
views_field_add_multi_join($data, /* see docs */);
}
Which is fairly simple to use and allows you to then perform aggregate functions across multiple field tables at once. You can then manually invoke a view $view->execute()
and pull the results off the view. There are examples of this in the views documentation.
The benefits of this approach over EntityFieldQuery is that you can manage the process in Views (which almost everyone will already be using) and allow it to perform the physical query building in less direct way which helps elevate possible breakage down the road. In addition many times you will want to display such aggregate data on an admin screen which you can then use the view to provide both a display and access the results in code for additional purposes.
_field_sql_storage_tablename($field)
and_field_sql_storage_columnname($field_name, $column
), which suits my current needs, but it isn't sustainable, so still interested in an answer to this question should one come.