Well, using SELECT * instead of SELECT [the fields you actually want] is ugly - it can hurt query optimisation techniques, and so cause it to run a bit slower than it otherwise might have. On top of that, it means you're transferring data from the database to the script that you don't need to. That takes time and memory as well.
echo <<<EOF;
For the big table at the end, the code would look a lot tidier using the Heredoc syntax (as illustrated by this paragraph). But note, too, that variable interpolation - whether using double-quoted strings or heredoc-quoted strings - is on the order of twice as slow as concatenating variables and strings together.
EOF;
Using something like "$promo_description" when $promo_description or '0' when 0 is intended leads to unnecessary typecasting, and is also a potential source of errors.
mysql_error() should not be used in production code; this is a security risk, as it effectively provides attackers with a debugger.
Why are you using mysql_fetch_array() sometimes and mysql_fetch_object() at others? (But then, I'm not too clear why the mysql_fetch_object() function was created in the first place.)