A nice way to build a related content algorithm
This was what I ended up writing to select nodes:

$query = db_select('node', 'n');
$query-&gt;addField('n', 'nid');
$query-&gt;addExpression('COUNT(n.nid)', 'ncount');
$query-&gt;innerJoin('taxonomy_index', 'ti', 'n.nid = ti.nid');
$query-&gt;condition('ti.tid', $tids, 'IN');
$query-&gt;condition('n.type', $types, 'IN');
$query-&gt;condition('n.nid', $node-&gt;nid, '&lt;&gt;'); // Exclude current node
$query-&gt;condition('n.status', 1); // Published
$query-&gt;condition(
  db_or()-&gt;condition('n.language', 'und')
         -&gt;condition('n.language', $node-&gt;language)
);
$query-&gt;groupBy('n.nid');
$query-&gt;groupBy('n.title');
$query-&gt;groupBy('n.created');
$query-&gt;orderBy('ncount', 'DESC');
$query-&gt;range(0, 10);

$results = $query-&gt;execute();


Kudos to Similar by Terms module, as I copied most of it from there. The magic happens when you order by ncount field.