I’m not entirely sure you can do this with a single query in MySQL as you can’t delete from tables which you reference in a sub-query. I would actually recommend doing this using wp-cli and using the WordPress API to delete the duplicate posts (which will also delete any post meta and associated term references):
global $wpdb;
$duplicate_titles = $wpdb->get_col("SELECT post_title FROM {$wpdb->posts} GROUP BY post_title HAVING COUNT(*) > 1");
foreach( $duplicate_titles as $title ) {
$post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title=%s", $title ) );
// Iterate over the second ID with this post title till the last
foreach( array_slice( $post_ids, 1 ) as $post_id ) {
wp_delete_post( $post_id, true ); // Force delete this post
}
}
Hope this helps.