code: def character_summary_table():
      
      # a database client/session to run queries in
      cl = client.get_client()
      session = cl.create_session()
  
      # Define the query. Note that we need to rename the two joined-in name columns,
      # to make the labels intelligible and to not have two identical column names in the output.
      # Also, we need a left outer join on the place of birth (instead of the default left inner join)
      # if we want results for characters that have no place of birth set.
      query = session.query(models.Character,
                            models.Universe.name.label('universe'),
                            models.Place.name.label('place_of_birth')) \
          .join(models.Character.universe) \
          .outerjoin(models.Character.place_of_birth)
  
      # download all data as a pandas DataFrame, index it by the character ID
      characters = cl.df_query(query).set_index('id')
  
      # query the number of movie appearances per character
      query = session.query(sa.func.count(models.MovieAppearance.id).label('movie_appearances'),
                            models.MovieAppearance.character_id) \
          .group_by(models.MovieAppearance.character_id)
  
      appearances = cl.df_query(query).set_index('character_id')
  
      # join both tables, sort by name
      df = characters.join(appearances, how='left').sort_values(by='name')
  
      # drop the foreign key columns (have no meaning outside our DB)
      df = df.drop(['universe_id', 'place_of_birth_id'], axis=1)
  
      # write output as both CSV and Excel; do not include index column
      df.to_csv(path.join(out_dir, "characters.csv"), encoding='utf-8', index=False)
      df.to_excel(path.join(out_dir, "characters.xlsx"), encoding='utf-8', index=False)
  
      session.close()
docs: Export a table listing all characters and their data
  
      Output is a CSV file and an Excel file, saved as 'characters.csv/.xlsx' in the output directory.