IME, MySQL är inte så bra på att optimera underfrågor - i synnerhet verkar det inte hantera push-predikat.
Jag är lite förvirrad över vad frågan egentligen är avsedd att returnera - särskilt "underföräldern"
Du skulle få en viss förbättring genom att lägga left_id och right_id i ett enda index.
Även om du också kommer att få en viss förbättring genom att rulla upp frågan till en lagrad procedur, med tanke på att du verkar gå igenom nästan hela datasetet varje gång en bättre lösning skulle vara att avnormalisera träddjupet och lagra det som ett attribut för varje nod. Du verkar faktiskt gå igenom det minst två gånger enbart i den yttre frågan.
Men jag märker att i slutet av frågan:
HAVING depth > 0
AND depth <= 1
Vilket säkert är samma sak som
HAVING depth=1
Vilket då ger ett helt annat sätt att optimera frågan (börja med att få alla noder där höger=vänster+1 för att hitta noderna utan barn och arbeta fram vägen för att kontrollera kategori-id).