You can use cross join with a 2-row virtual table to disable player_* columns and then group the results, for example:
SELECT player, COUNT(*) AS total_count FROM ( SELECT CASE WHEN x.is_in THEN t.player_in ELSE t.player_out END AS player FROM mytable t CROSS JOIN (SELECT TRUE AS is_in UNION ALL SELECT FALSE) x ) s GROUP BY player ;
Thus, each row of the source table is essentially duplicated, and each copy of the row contains either player_in or player_out , depending on whether the derived table column is is_in TRUE or FALSE to form a single player column. This promotion method may work better than the UNION method proposed by @Bohemian , because this method (physical) table is only transmitted once (but you will need to test and compare both methods to determine if there is substantial benefit for this approach in your particular situations).
To count the number of incoming and outgoing numbers, as you requested in one of your comments on the above answer, you can expand your original sentence as follows:
SELECT player, COUNT( is_in OR NULL) AS in_count, COUNT(NOT is_in OR NULL) AS out_count, COUNT(*) AS total_count FROM ( SELECT x.is_in, CASE WHEN x.is_in THEN t.player_in ELSE t.player_out END AS player FROM mytable t CROSS JOIN (SELECT TRUE AS is_in UNION ALL SELECT FALSE) x ) s GROUP BY player ;
As you can see, the view now additionally returns the is_in column by itself, and the column is used in two conditional aggregates to calculate how many times a player has been in and out. (If you're interested, the OR NULL trick is explained here .)
You can also rewrite COUNT(condition OR NULL) records as SUM(condition) . This will certainly cut down on both expressions, some will also find a way to SUM count clearer / more elegant. In any case, there probably will not be any difference in performance, so choose the method that best suits your taste.
A demo version of SQL Fiddle of the second query can be found here .