我有许多“实际”和“历史伴侣表”(可以这么说),最后的结构如下:
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
如果我在“实际”表中插入(或更新或删除)记录,触发器会将受影响的记录放入“历史表”中,其中date_deal = Geddate()、type_deal = i|u|d(分别用于插入、更新和删除触发器)和num 作为 autoinc 唯一值
所以问题是如何获取在特定日期有效的每个不同值的最后一条记录,并从最终结果记录中排除 type_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 DropCleanbuffers 指令。实际工作的服务器有超过 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'
61sec @ 2'316'890rec 真实的,4sec @ 191'533 测试
拉胡尔:
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'
62sec @ 2'316'890rec 真实的,4sec @ 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'
真实的 76 秒 @ 2'316'890rec,测试时 5 秒 @ 191'533
到目前为止,原始和 Rahul 的速度最快,而 George 的速度不是那么快。