Sql server 子查询的更有效替代方案

Sql server 子查询的更有效替代方案,sql-server,subquery,Sql Server,Subquery,我有很多实际的和历史的配对表,可以这样说,最后一个表的结构如下: values| date_deal | type_deal | num (autoinc) value1| 01.01.2012 | i | 1 value1| 02.01.2012 | u | 2 value2| 02.01.2012 | i | 3 value2| 03.01.2012 | u | 4 value1| 04.01.2012 |

我有很多实际的和历史的配对表,可以这样说,最后一个表的结构如下:

values|  date_deal | type_deal | num (autoinc)
value1| 01.01.2012 |         i |   1
value1| 02.01.2012 |         u |   2
value2| 02.01.2012 |         i |   3
value2| 03.01.2012 |         u |   4
value1| 04.01.2012 |         d |   5
value2| 05.01.2012 |         u |   6
value2| 08.01.2012 |         u |   7
若我在实际表中插入、更新或删除记录,触发器会将受影响的记录放入历史记录表中,并分别键入插入、更新和删除触发器的日期_deal=Geddate,键入_deal=I | u | d,num作为autoinc唯一值

所以问题是如何获得在特定日期有效的每个不同值的最后一条记录,并从最终结果记录中排除类型为_deal='d'的记录,因为该记录当时已从实际表中删除,我们不希望与之有任何关联

我大部分时间都是这样做的:

SELECT  *
FROM    t_table1 t1
WHERE   t1.num = (  SELECT  MAX(num)
                    FROM    t_table1 t2
                    WHERE   t2.[values] = t1.[values]
                        AND t2.[date_deal] < @dt)
    AND t1.[type_deal] <> 'D'
但有时效果很慢。我正在寻找更有效的替代方案。求求你,救命

所以,更新。 谢谢你的回复,朋友们

我已经在实际服务器和测试服务器上进行了一些测试。 为了将这些不同的方法放在同一个联盟中,我决定我们应该从源表中获取所有字段

测试服务器有低于200K的记录,我也有幸使用DBCC FreeProcCache 和DBCC DROPCLEANSBUFFERS指令。实际工作的服务器有超过230万条记录,而且自..以来也没有删除buff或缓存的选项。。好真正的用户正在使用它。所以它只被删除了一次,之后我就得到了结果

以下是两台服务器上的实际查询及其花费的时间:

原件:

DECLARE @dt datetime = CONVERT(datetime, '01.08.2013', 104)

SELECT  *
FROM    [CLIENTS_HISTORY].[dbo].[Clients_all_h] c
WHERE   c.num = (   SELECT  MAX(num)
                    FROM    [CLIENTS_HISTORY].[dbo].[Clients_all_h] c2
                    WHERE   c2.[AccountSys] = c.[AccountSys]
                        AND date_deal <= @dt)
    AND c.type_deal <> 'D'
在2'316'890rec处61秒,在实际测试中,在191'533处4秒

拉胡尔:

SELECT  *
FROM    [CLIENTS_HISTORY].[dbo].[Clients_all_h] c
GROUP BY [all_fields]
HAVING  c.num = (   SELECT  MAX(num)
                    FROM    [CLIENTS_HISTORY].[dbo].[Clients_all_h] c2
                    WHERE   c2.[AccountSys] = c.[AccountSys]
                        AND date_deal <= @dt)
    AND c.type_deal <> 'D'
在2'316'890rec处62秒,在实际测试中4秒,在191'533处 几乎相等

乔治的一些主要变化:

SELECT * FROM 
(
SELECT  *,
        ROW_NUMBER() OVER(PARTITION BY accountsys ORDER BY num desc) AS aa
FROM    [CLIENTS_HISTORY].[dbo].[Clients_all_h] c
WHERE   c.date_deal < @dt) as a
WHERE   aa=1
    AND type_deal <> 'D'
在2'316'890rec处76秒,在实际测试中为76秒,在191'533处为5秒


到目前为止,original和Rahul的速度最快,而George的则不那么快

尝试使用GROUPBY..HAVING子句

SELECT  *
    FROM    t_table1 t1
    GROUP BY [column_names]
    HAVING   t1.num = (  SELECT  MAX(num)
                        FROM    t_table1 t2
                        WHERE   t2.[values] = t1.[values]
                            AND t2.[date_deal] < @dt)
        AND t1.[type_deal] <> 'D'

我认为row_num可能对您有用,如下所示:

select
   *
from
(
   select
     *,
   row_number() over( partition by date_deal order by num) as aa
      from
   t_table1 t1
   where
     t1.[type_deal] <> 'D'
) as a
where
   aa=1

对于任何性能问题,首先要做的是查看。可能不是子查询导致性能问题。SQL Server经常将子查询优化为联接或等效查询。请告诉我您的日期不是varchars?谢谢您的想法,Justin。看起来SQLServer实际上是在优化查询到内部JOINNo,Joel。是DateTime你桌上有什么索引?