Slow postgres query that uses quick sort instead of hash-aggregate
You can see the flaw here,


  Hash Cond: (((event_page_2016_8.person_alias)::text = (a.alias)::text) AND ((event_page_2016_8.session_id)::text = (s.session_id)::text))


It thinks that condition returns 2 rows. Instead it returns 11,861,365. If it returned 2 rows, a quick sort almost certainly would have been faster. The question is primarily why does it think that it's so far off there..

You may want to try to refresh the statistics (or even raising the statistics target for those tables) with ANALYZE event_page_2016_8 alias session, or see what could be returning so many rows to begin with.

Also this conditional doesn't make much sense to me

join alias as A
  on (O.person_alias = A.alias)
left outer join session as S
  on (O.session_id = S.session_id) 
join alias as A1
  on ( A1.alias = S.person_alias and A.person_id = A1.person_id)


Maybe I'm missing something. So you're self-joining A to A1 on person_id but also S.person_alias which has to share a session_id.. Why not just 

join alias as A
  on (O.person_alias = A.alias)
join session as S
  USING (session_id)


And leave out A1 entirely? You're not using it in the SELECT list?