You can't just take 3 TIME IO measurements and average them and say that a faster query is necessarily better than a slower one.
Sometimes it just seems like a dark art.
First, start using Profiler instead of TIME IO; use Reads, Writes, CPU, and Duration as your go-to columns, and I generally work at a SQL:Batch Completed and RPC:Completed event level; you can also turn on the SQL:Statement Completed event if that helps you, but always use the batch as your guide to results. You'll have a lot more information, _and_ TIME IO doesn't report UDF usage correctly (i.e. at all).
Second, don't look at "faster" first. Look at reads, writes, and CPU first (i.e. resources used), and know your systems (the whole system). On many systems, IO is the general bottleneck, so trading more CPU for less reads and writes is a good trade. On some systems, the opposite. On a few, they're more or less equal. Duration can also be seriously impacted by parallel plans or the lack thereof; in some cases, you may need to spend more resources to meet a duration limit... at the expense that you're now much more vulnerable to failing that limit if too many sessions run that batch at overlapping times (i.e. at "the same time"; for instance, if several users all schedule it for 9:00a.m.).
After a point, it is a dark art; like all arts, practice and experience is critical. Also, like some arts, you can easily just keep experimenting - try writing queries three or five different ways, and watch the differences in Profiler. That's roughly the point of "premature optimization", I'd say! Before that point, it's very scientific and simple:
0) Know the data
1) Know the business goal of the SQL you're looking at
2) Remove everything not required by the business goal
2a) If your screen is now blank, it never worked right
3) Remove everything no longer required because it was required by something not required by the business goal
4) Good query design - set based, simple, efficient, using only the rows and columns required
5) Schema integrity
6) Data integrity
7) Intermediate result integrity - don't cause problems between the data and the results!
7a) If there's a DISTINCT, there are probably incomplete or incorrect joins or join criteria resulting in too many rows being used... and some may be the wrong rows, or the query may have an intermediate cartesian product
7b) If the DISTINCT is really required, use it at the finest granularity possible (in a derived table, #temp table, etc.)
7c) Verify that if you expect a join to be 1:1, that you're getting 1:1 results on the _entire_ data set, not just a sample - many constructs (select @var = col1 from tab1) will return only the first row found without any warning that it found multiple rows.
8) Final result integrity - return, accurately, exactly what is required. No more, no less.
After that are the dark arts, to be used only when the benefits outweigh the costs (or as a training exercise) involve writing the query three to five different ways and watching the differences between each, indexing, FK constraints, SSD's, etc. etc., and know that results can vary environment to environment, version to version, and from one hour to the next (based, say, on what buffers usually contain at any given time). They are, in fact, scientific, but we rarely have enough information to plan them out purely scientifically.
P.S. either discard the first result out of a set, or if the "first time" cost is what's important, after each try, drop clean buffers for relevant tables and clearing the procedure cache for the relevant statements.
P.P.S. Resource Monitor is very useful for a fast view of disk IO latency vs CPU vs memory vs network.
ETA scientific example.