WP_Query meta_query results date by date

My idea is following.

1. Get the array of all meta dates your events have. DISTINCT in the MySQL query means do not include duplicates.

<?php
/*
 * From https://wordpress.stackexchange.com/a/9451/11761
 */
function get_all_possible_meta_dates( $key = 'event_dates_wp', $type="page", $status="publish" )
{

    global $wpdb;

    $result = $wpdb->get_col( $wpdb->prepare( "
        SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = '%s'
        AND p.post_status="%s"
        AND p.post_type="%s"
    ", $key, $status, $type ) );

    return $result;
}

2. Loop through all posts having event_dates_wp meta key and get the posts object. You need it once.

3. Compare each post meta to the possible dates you have. If there is match, print it out.

<?php
function print_posts_by_meta_dates()
{

    $args = [
        'post_type' => 'event',
        'order' => 'ASC',
        'orderby' => 'meta_value',
        'meta_key' => 'event_dates_wp',
        'posts_per_page' => -1,
    ];

    // all events having `event_dates_wp`
    $loop = new WP_Query( $args );

    // all posssible event dates
    $distinct_meta_dates = get_all_possible_meta_dates();

    foreach( $distinct_meta_dates as $event_meta_date ) {

        // date header
        echo '<h1>' . $event_meta_date . '</h1>';

        // loop through all events
        foreach( $loop->posts as $event ) {

            // get current event dates array
            $event_all_dates = get_post_meta( $event->ID, 'event_dates_wp', false );

            // compare
            if( in_array( $event_meta_date, $event_all_dates ) ) {

                // post name
                echo '<p>' . $event->post_name;

            }
        }
    }
}

4. Print the post list using print_posts_by_meta_dates() function in a template.

5. Or create the shortcode to use inside the post or page.

add_shortcode( 'test_shortcode', 'print_posts_by_meta_dates' );

You’ll get something similar to:

  • 20180801
    • test-page-1
  • 20180802
    • test-page-1
    • test-page-2
    • test-page-3
  • 20180803
    • test-page-2
    • test-page-3

Remember, do not separate custom fields with e. g. comma, but add them separately:

enter image description here