Have a look at the Query Plan and see the difference (if any) between the two?SET SHOWPLAN_TEXT ONGO ... put query here ...SET SET SHOWPLAN_TEXT OFFGO
Note that string dates should be in the form "yyyymmdd" (no hyphens) to be unambiguous - so you might like to try changing "2010-03-01 00:00:00.000" to "20100301" - but I doubt that would make a difference to performance.where receipt_no in( select distinct p.receipt_no from posdata p, va_pos v where v.register_num = p.register_num and p.server_time > '2010-03-01 00:00:00.000' and p.server_time < '2010-03-31 00:00:00.000' and v.start_time > '2010-03-01 00:00:00.000' and v.start_time < '2010-03-31 00:00:00.000' and p.server_time >= v.start_time and p.server_time <= v.end_time and rule_name like '%gas%' and p.value_char like '4002')
would be better done as an EXISTS - you are making a list with "select distinct p.receipt_no" which requires finding all values and then de-duping them, whereas EXISTS would terminate with "success" on the first one that it found.You are also repeating the inner WHERE clause in the outer query - but there is no need surely? That may be causing SQL to make a different query plan. and pos.value_char = '4002' and pos.server_time > '2010-03-01 00:00:00.000' and pos.Server_time < '2010-03-31 00:00:00.000'
is also performed by the inner query, so receipt_no can only be within that range anyway.Thus I think it can be optimised to:SELECT TOP 100 pos.item as item, sum(pos.quantity) as quantity, count(*) as cnt, sum(value_num) as amount FROM posdata AS pos WHERE EXISTS( SELECT * FROM va_pos AS v WHERE v.register_num = pos.register_num and v.start_time > '20100301' and v.start_time < '20100331' and pos.server_time >= v.start_time and pos.server_time <= v.end_time and rule_name like '%gas%' ) and pos.value_char = '4002' and pos.server_time > '20100301' and pos.Server_time < '20100331'GROUP BY pos.itemORDER BY quantity desc
and even then the and pos.server_time > '20100301' and pos.Server_time < '20100331'
may be superfluous.Just looking at the query, and the actual date-limits set, did you really mean to use GREATER THAN rather than GREATER THAN OR EQUAL (ditto for LESS THAN instead of LESS THAN OR EQUAL)? and v.start_time > '20100301' and v.start_time < '20100331'... and pos.server_time > '20100301' and pos.Server_time < '20100331'
but that has next-to-nothing to do with using Parameters instead of String values for the WHERE clause ranges. Parameters will be better, anyway, because the query will be cached (which is a separate issue to whether Parameter Sniffing will help / hinder)