I would agree with Harry's generalization. Typically it works well due to the smaller, more compact (e.g. fixed-length datatypes), tables.
I would never use MySQL as a good case study for complex queries since MySQL's optimizer is piss-poor and doesn't handle really anything well.
The place I've noticed denormilization helps a bit is with large aggregate queries, such as:
Generally this is a 'brute force' operation and the optimizer can't do much except count rows (index or table) and do other high physical I/O-based operations, which is not good.
SELECT COUNT( someID ),
MAX( t2.blah )
FROM table1 t1
INNER JOIN table2 t2 ON t1.ID = t2.ID
WHERE t1.somecol BETWEEN 23 AND 340000
I think putting postcodes in another table is fine. If not, how do you let the user enter the data? By hand in a textbox and simply store the INT value in the database? Are you going to validate it at all? If so, you'll need to store the values somewhere. Plus, it would allow you to do this:
So you also have your state linkage so that you don't have to ask the user for it (could save space there).
CREATE TABLE postcode(
state CHAR( 2 )
CREATE TABLE state(
name VARCHAR( 100 ),
stateabbr CHAR( 2 ),
Back to the query at hand, jdulberg what exactly are you trying to do? If we know your reqirements we can make a more informed, and educated, stab at your problem.