Removing the uses of MySQL temporary tables
Sometimes i use temporary tables to create complex reports. A relatively simple (and meaningless) example could be something like

drop temporary table if exists some_temporary_table1;
create temporary table some_temporary_table1
    select t1.someColumn, max(t2.someOtherColumn) as someMax
    from some_table1 t1
    join some_table2 t2 using(someJoinColumn)
    where t1.someConditionColumn = 'someConditionValue'
    group by t1.someColumn
;

drop temporary table if exists some_temporary_table2;
create temporary table some_temporary_table2
    select tmp1.someColumn, tmp1.someMax, min(t3.someCompletelyOtherColumn) as someMin
    from some_temporary_table1 tmp1
    join some_table3 t3 using(someJoinColumn)
    where t3.someOtherConditionColumn = 'someOtherConditionValue'
    group by tmp1.someColumn, tmp1.someMax
;

select *
from some_temporary_table2 tmp2
join some_table3 t3 using(someDifferentJoinColumn)
where t3.someFancyConditionColumn = 'someFancyConditionValue'


Same result can be achieved without temporary tables, eliminating them step by step.

Step 1 - eliminate some_temporary_table1, replacing its occurrence with its creating code:

drop temporary table if exists some_temporary_table2;
create temporary table some_temporary_table2
    select tmp1.someColumn, tmp1.someMax, min(t3.someCompletelyOtherColumn) as someMin
    from (
        select t1.someColumn, max(t2.someOtherColumn) as someMax
        from some_table1 t1
        join some_table2 t2 using(someJoinColumn)
        where t1.someConditionColumn = 'someConditionValue'
        group by t1.someColumn
    ) tmp1
    join some_table3 t3 using(someJoinColumn)
    where t3.someOtherConditionColumn = 'someOtherConditionValue'
    group by tmp1.someColumn, tmp1.someMax


Step 2 - eliminate some_temporary_table2

select *
from (
    select tmp1.someColumn, tmp1.someMax, min(t3.someCompletelyOtherColumn) as someMin
    from (
        select t1.someColumn, max(t2.someOtherColumn) as someMax
        from some_table1 t1
        join some_table2 t2 using(someJoinColumn)
        where t1.someConditionColumn = 'someConditionValue'
        group by t1.someColumn
    ) tmp1
    join some_table3 t3 using(someJoinColumn)
    where t3.someOtherConditionColumn = 'someOtherConditionValue'
    group by tmp1.someColumn, tmp1.someMax
) tmp2
join some_table3 t3 using(someDifferentJoinColumn)
where t3.someFancyConditionColumn = 'someFancyConditionValue'


If more temporary tables are involved, this can end up in a highly unreadable (and unmaintainable) code. To keep your code readable you can build the query in PHP using string variables for subqueries:

$subQuery1 = "
    select t1.someColumn, max(t2.someOtherColumn) as someMax
    from some_table1 t1
    join some_table2 t2 using(someJoinColumn)
    where t1.someConditionColumn = 'someConditionValue'
    group by t1.someColumn
";

$subQuery2 = "
    select tmp1.someColumn, tmp1.someMax, min(t3.someCompletelyOtherColumn) as someMin
    from ( {$subQuery1} ) tmp1
    join some_table3 t3 using(someJoinColumn)
    where t3.someOtherConditionColumn = 'someOtherConditionValue'
    group by tmp1.someColumn, tmp1.someMax
";

$mainQuery = "
    select *
    from ( {$subQuery2} ) tmp2
    join some_table3 t3 using(someDifferentJoinColumn)
    where t3.someFancyConditionColumn = 'someFancyConditionValue'
";


which is similar to the original temporary table solution.

In terms of performance - it usually doesn't make much difference. 
Sometimes the temporary-tables-solution is faster. 
Sometimes it's the one-statement-solution. But mostly it's not more than 10%.
In an old example i just tested, the one-statement-solution was a bit was faster,
even though i gave some hints like to use smaller data types (smallint instead of bigint),
creating indexes on temp tables to use for the next join and using a temp table twice.
In another example i remember from work, the temporary-tables-solution has been faster,
even though i didn't use any hints.