Boa noite Carlos, tudo bem com você?
Percebi que você estudou outras possibilidades do sql com o Python, parabéns pela iniciativa. Como não consegui reproduzir o seu erro, vou explicar o que eu fiz e qual saída obtive, tudo bem?
Criei as tabelas aluno, curso e matricula com o seguinte código:
nomes.to_sql('aluno', engine)
cursos.to_sql('curso', engine)
matriculas.to_sql('matricula', engine)
Executei o código que você postou:
query = 'select curso.nome, count(*) from curso join matricula on matricula.curso_id = curso.id join aluno on aluno.id = matricula.aluno_id;'
pd.read_sql(query, engine)
E tive a seguinte saída:
|  | nome | count(*) | 
|---|
| 0 | Análise de dados | 859 | 
Imaginei que não era esse resultado que você estava esperando, já que 859 é o número total de matrículas existentes e não a quantidade de matrículas do curso Análise de dados. Você pode validar isso executando matriculas.shape[0], a saída será 859.
Mas ainda queremos a quantidade de matrículas de cada curso, como conseguimos fazer isso com a biblioteca do pandas? Podemos agrupar o nosso dataframe matriculas pela coluna 'curso_id' contando quantas vezes ele aparece no grupo, assim cada grupo teria o total de matrículas de cada curso. Legal, temos as quantidades, mas como fazemos para mostrar o nome do curso juntamente com as quantidades? Podemos fazer isso cruzando a coluna  'curso_id' do dataframe matriculas  com a coluna id do dataframe  cursos. O instrutor Guilherme resolveu esse problema da seguinte maneira na aula:
matriculas_por_curso = matriculas.groupby('curso_id').count().join(cursos['nome']).rename(columns={'aluno_id':'quantidade_de_alunos'})
matriculas_por_curso.head(3)
Saída: 
| curso_id | quantidade_de_alunos | nome | 
|---|
| 1 | 62 | Lógica de programação | 
| 2 | 52 | Java para Web | 
| 3 | 25 | C# para Web | 
Agora temos um novo dataframe matriculas_por_curso com as informações que queríamos. 
Como você estava estudando outras possibilidades com sql, fazendo um pequeno ajuste, adicionando group by curso.nomeao final da sua query, vamos conseguir fazer a mesma coisa que fizemos com pandas com sql, olha só que legal:
query = 'select curso.nome, count(*) from curso join matricula on matricula.curso_id = curso.id join aluno on aluno.id = matricula.aluno_id group by curso.nome;'
pd.read_sql(query, engine)
Saída dos 10 primeiros:
|  | nome | count(*) | 
|---|
| 0 | .NET para web | 56 | 
| 1 | Análise de dados | 82 | 
| 2 | Boas práticas em Java | 67 | 
| 3 | C# para Web | 25 | 
| 4 | Cursos de Python | 59 | 
| 5 | Código limpo com C# | 12 | 
| 6 | Desenvolvendo jogos | 31 | 
| 7 | Estatística básica | 16 | 
| 8 | Hardware básico | 22 | 
| 9 | Internet das coisas | 44 | 
Outra forma de obter as mesmas informações com sql é :
query = 'select count(curso_id) as quantidade_de_alunos, nome from matricula join curso on matricula.curso_id = curso.id group by matricula.curso_id'
pd.read_sql(query, engine)
Saída dos 10 primeiros:
|  | quantidade_de_alunos | nome | 
|---|
| 0 | 62 | Lógica de programação | 
| 1 | 52 | Java para Web | 
| 2 | 25 | C# para Web | 
| 3 | 33 | Ruby on Rails | 
| 4 | 59 | Cursos de Python | 
| 5 | 17 | PHP com MySql | 
| 6 | 56 | .NET para web | 
| 7 | 37 | Novas integrações com Java | 
| 8 | 70 | TDD com Java | 
| 9 | 12 | Código limpo com C# | 
Espero ter conseguido ajudar, mas qualquer coisa é só mandar mensagem viu?!
Abraço e bons estudos.
Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.Bons Estudos!