If I was in your situation, I'd used a different approach.
Simply add an hidden meta field automatically when goals_made is updated.
E.g.
add_action('updated_postmeta', 'update_goal_made', 20, 4);
function update_goal_made( $meta_id, $object_id, $meta_key, $_meta_value ) {
if ( $meta_key != 'goals-made') return; // run only when update meta 'goals-made'
// get the goals-against for post
$against = get_post_meta($object_id, 'goals-against', true) ? : 1;
// if 'goals-made' > 'goals-against' create/update a field '_goals-won' setted to 1
if ( intval($_meta_value) > intval($against) ) {
update_post_meta($object_id, '_goals-won', '1');
} else {
// if not delete '_goals-won' post meta (if exists)
delete_post_meta($object_id, '_goals-won');
}
}
Now to retrieve the posts where _goals-won
exists, simply run a meta query:
$args = (
'posts_per_page' => -1,
'meta_query' => array( array('meta_key'=>'_goals-won') )
);
$won_posts = get_posts($args);
EDIT
After some works on GhostToast answer I can give you also the right SQL query to get the same result.
global $wpdb;
$won_posts = $wpdb->get_results( "
SELECT $wpdb->posts.*
FROM $wpdb->posts
INNER JOIN $wpdb->postmeta AS mt1 ON ( $wpdb->posts.ID = mt1.post_id )
INNER JOIN $wpdb->postmeta AS mt2 ON ( $wpdb->posts.ID = mt2.post_id )
WHERE mt1.meta_key = 'goals-made'
AND (
mt2.meta_key = 'goals-against'
AND CAST( mt1.meta_value AS UNSIGNED ) > CAST( mt2.meta_value AS UNSIGNED )
)
GROUP BY $wpdb->posts.ID
" );
Side note:
If someone write the SQL statement that handle your request, sure that SQL statement will be less performant then the simplest meta query like the first posted.