As Tim Malone said, WP_Query isn't going to return multiple copies of the same post in its result set. I think you have a design problem and I would suggest you use parent/child posts rather than post meta to accomplish what you want.
The following is one approach to doing this. First, register both post types:
// The parent event type
// There will be one of these for Radio Show and TV Show
register_post_type( 'event', $args );
// A non-public event type for each "occurrence" of an event
// There will be two of these for each Radio Show and TV Show
register_post_type( 'event_occurrence', array(
// add all of your usual $args and then set public to false
'public' => false,
) );
Then, when saving your event
post, don't save the start/end times as post meta on that post object. Instead use those dates to create event_occurrence
posts for each occurrence, with the start and end times saved there.
$occurrence_id = wp_insert_post( array(
// add all of your occurrence details and then set the parent
// to the `event` post that's being saved
'post_parent' => <event_post_id>,
// Set the post date to the start time for efficient ordering
'post_date' => $start_time,
) );
// Save the end time as post meta
// Save it as a Unix timestamp so that we can compare it in the query
update_post_meta( $occurrence_id, 'end_time', strtotime( $end_time ) );
Now you should have the following posts in the database:
Radio Show
Radio Show Instance 1
Radio Show Instance 2
TV Show
TV Show Instance 1
TV Show Instance 2
You can then query the occurrences like this:
$args = array(
// Only fetch occurrences
'post_type' => 'event_occurrence',
// Retrieve only future occurrences
'date_query' => array(
array(
'after' => 'now',
)
),
// use a reasonably high posts_per_page instead of -1
// otherwise you could accidentally cripple a site
// with an expensive query
'posts_per_page' => 500,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'end_time',
'value' => time(),
'compare' => '>='
),
),
// They'll be ordered by start date.
// ASC starts with earliest first
'order' => 'ASC',
);
Our loop will now contain four posts:
Radio Show Instance 1
Radio Show Instance 2
TV Show Instance 1
TV Show Instance 2
So while you're looping through the occurrences, you can access the parent post of each occurrence to get the overall event data. You can do this with a simple function:
$parent_event_id = wp_get_post_parent_id( get_the_ID() );
However, this will result in a lot of extra queries to the database which will effect performance. Instead, I'd recommend you run a separate query for the primary event
posts, and then pull them from those results, so you're only making one additional query to the database:
$args = array(
'post_type' => 'event',
'date_query' => array(
array(
'after' => 'now',
)
),
'posts_per_page' => 500,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'end_time',
'value' => time(),
'compare' => '>='
),
),
'order' => 'ASC',
);
$events = new WP_Query( $args );
So your $occurrences loop would look like this:
$occurrences = new WP_Query( $occurrences_args );
while( $occurrences->have_posts() ) {
$occurrences->the_post();
// Get the parent event data
$parent_event_id = wp_get_post_parent_id( get_the_ID() );
$parent_event = null;
foreach ( $events->posts as $post ) {
if ( $post->ID == $parent_event_id ) {
$parent_event = $post;
break;
}
}
// Now you can use the loop to access the
// occurrence data and use $parent_event to
// access the overall event data
}