Instead of storing (username, salt, hash(salt, password)) you can store in one table (username, salt) and another (hash(salt, password, username)). This is no more secure than hash(salt, password) if salts (plural) are unique. (Which they should be. You then force attacks on individual accounts instead of the whole group. A cracker checking offline for hash("unique per user salt", "password1") gets less information than when they can get hash("global salt", "password1"), which yields the set of all users that have that password.)
If you have only a site-global password salt (you should instead do per user) then storing (hash(global salt, password, user name)) is better than (hash(global salt, password)) for similar reasons.
One small problem with the global salt scheme is that leaks some information if a user starts with say "password1", changes it to "password2", then back to "password1" again. In that case someone who had previous cracked that user's first password that person will see that the hash for the old username password combination is still in the database. They then know that they can use a users old password again. (I would assume they would try the user's old password and variations on that password anyway, if they crack the user's old password, however.) Use a new unique salt (random with enough entropy that collisions are unlikely) every time a person changes their username or password to prevent that.
From a non-crypto point of view the (username, salt, password hash) construct has the benefit that it only needs one query with one unit of latency. The other you need to wait one unit of time to get (username, salt) back and another for (hash of username salt and password) to be checked (and reported back whether its present or absent (which can still be done O(1) time with a hash table (the data structure) index)). Of course if you're using password stretching or infrequently do authentication checks then that extra latency is insignificant.