Tek sorguda nasıl olur tam bilmiyorum ama mantık olarak önce tüm kategorileri çekip sonra diğer tabloda o kategoride bilgi varsa onları getirmek gerekiyor.  Şöyle yazayım siz buna uygun deneyin.

<?php

$categories = $db->query("SELECT * FROM kategoriler")->fetchAll(PDO::FETCH_ASSOC);

if($categories) {

 foreach($categories as $category) {

  $posts = $db->prepare("SELECT * FROM posts WHERE category_id=?");

  $posts->execute(array($category["id"]));

  $result = $posts->fetchAll(PDO::FETCH_ASSOC);

   foreach($result as $post) {

     // döngüye girecek tasarımı buraya yazabilirsiniz.

   }


}

}

?>