Order posts by date

Three loops

http://codex.wordpress.org/Class_Reference/WP_Query#Time_Parameters

$time = time();

foreach ( range( 0, 2 ) as $yesterday ):

    // get relative time offset by $yesterday days
    $rel_time = strtotime( "-$yesterday days", $time );

    // get the digits
    $year = date( 'Y', $rel_time );
    $day = date( 'd', $rel_time );
    $month = date( 'm', $rel_time );

    // get the posts
    foreach ( get_posts( 'year=" . $year . "&monthnum=' . $month . '&day=' . '$day&posts_per_page=3' ) as $post ):
        setup_postdata( $post );

        the_title();
        the_content();
    endforeach;

endforeach;

You can also pivot around the $time in other more efficient ways. Remember 3 loops = 3 database queries.

SQL

http://codex.wordpress.org/Class_Reference/wpdb

global $wpdb;
$sql = "SELECT * FROM `$wpdb->posts` WHERE 1=0";

$time = time();

for ( $i = 0; $i < 3; $i++ ) {
    $time = strtotime( "-1 day", $time ); // deduct one day every time

    $year = $wpdb->escape( date( 'Y', $time ) );
    $day = $wpdb->escape( date( 'd', $time ) );
    $month = $wpdb->escape( date( 'm', $time ) );

    $sql .= " OR `ID` IN ( SELECT `ID` FROM `$wpdb->posts` WHERE YEAR(`post_date`) = '$year' AND MONTH(`post_date`) = '$month' AND DAY(`post_date`) = '$day' LIMIT 3)";
}

foreach( $wpdb->get_results( $sql, OBJECT_K ) as $post ):
    setup_postdata( $post );
    // ...display stuff
endforeach;

This results in something like:

SELECT *
FROM `wp_posts`
WHERE 1=0
    OR `ID` IN (
        SELECT `ID`
        FROM `wp_posts`
        WHERE YEAR(`post_date`) = '2012'
            AND MONTH(`post_date`) = '03'
            AND DAY(`post_date`) = '30'
        LIMIT 3)
    OR `ID` IN (
        SELECT `ID`
        FROM `wp_posts`
        WHERE YEAR(`post_date`) = '2012'
            AND MONTH(`post_date`) = '03'
            AND DAY(`post_date`) = '29'
        LIMIT 3)
    OR `ID` IN (
        SELECT `ID`
        FROM `wp_posts`
        WHERE YEAR(`post_date`) = '2012'
            AND MONTH(`post_date`) = '03'
            AND DAY(`post_date`) = '28'
        LIMIT 3)

Big query, with 3 subqueries. Hairy.

Escape counters

$seendays = array(); // keep track of the day numbers

if ( have_posts() ) : while ( have_posts() ) : the_post();
    if ( isset( $seendays[get_the_date( 'Y-m-d' )] ) && $seendays[get_the_date( 'Y-m-d' )] > 3 ) continue;

    $seendays[get_the_date( 'Y-m-d' )] = isset( $seendays[get_the_date( 'Y-m-d' )] ) ? $seendays[get_the_date( 'Y-m-d' )] + 1 : 1;

    // ...display stuff
endif;

All three methods are quite raw, and will require some fine-tuning here and there. Hope this helps.