我原本写过以下内容
SELECT t1.TransactionNumber
FROM t1
JOIN
(
SELECT MAX(id) id
FROM t1
WHERE Period BETWEEN '01-11-2013' and '01-12-2014'
GROUP BY AccountNumber
) t2
on t1.id= t2.id
但它太慢了。花了大约20秒,所以作为测试,我将其更改为以下
SELECT MAX(id) AS id
INTO #t2
FROM t1
WHERE Period BETWEEN '01-11-2013' and '01-12-2014'
GROUP BY AccountNumber
SELECT t1.id
FROM t1
JOIN #t2 t2
ON t1.id= t2.id
第二个查询只需1秒即可运行。第二个查询使用PK密钥执行索引查找,而第一个密钥执行扫描。
注意:id是聚集在t1表上的主键。
答案 0 :(得分:1)
这是猜测,但可能是因为主键上的统计信息不适合您。如果查询优化器认为您只是从内部联接返回10条记录,而是返回100,则它会溢出内存缓冲区,然后最终必须将子查询的结果写入磁盘。如果您发布查询执行计划结果,它应该变得非常明显。
答案 1 :(得分:0)
你不能把所有的条件都放在ON部分吗?
SELECT t1.id
FROM t1
JOIN
(
SELECT id
FROM t1
WHERE <condition>
) t2
on t1.id = t2.id;
转化为
SELECT t1.id
FROM t1
JOIN t1 as t2
ON t1.id = t2.id AND <condition>
更新:
Retrieving the last record in each group 该链接显示如何检索组中的最后一条记录。 SQL正在关注
SELECT m1.*
FROM messages m1 LEFT JOIN messages m2
ON (m1.name = m2.name AND m1.id < m2.id)
WHERE m2.id IS NULL;
您可以使用此而不是group by
答案 2 :(得分:0)
这两个查询之间的主要区别在于第二个查询是严格查询索引!!!
SELECT t1.TransactionNumber
FROM t1
JOIN
(
SELECT MAX(id) id
FROM t1
WHERE Period BETWEEN '01-11-2013' and '01-12-2014'
GROUP BY AccountNumber
) t2
on t1.id= t2.id
查询transactionNumber列因此无法使用表上的undex,第二个查询仅使用ID。这将使世界变得与众不同。
答案 3 :(得分:0)
连接消耗大量资源,计算结果需要再次与表重新连接,因此需要很长时间。当您使用临时表时,结果已经存储在临时表中,因此连接条件比子查询运行得更快。
答案 4 :(得分:0)
试试这个:
SELECT t1.TransactionNumber t1 WHERE t1.id = (SELECT MAX(id) id FROM t1 WHERE Period BETWEEN '01-11-2013' and '01-12-2014' GROUP BY AccountNumber)
答案 5 :(得分:0)
通常,性能(尽管需要更多代码)更好地显式声明列和数据类型而不是SELECT..INTO
。这可能会更快:
CREATE TABLE #t2
(
id INT
);
INSERT INTO #t2(id)
VALUES
(
SELECT MAX(id)
FROM t1
WHERE Period <= '01-11-2013'
AND Period > '01-12-2014'
GROUP BY AccountNumber
);
SELECT t1.id
FROM t1
JOIN #t2 t2
ON t1.id= t2.id
答案 6 :(得分:0)
不同之处在于,在第一个查询中,引擎不知道t2中的结果数(我假设与t1计数相比数量相对较小,但SQL服务器事先并不知道)。 因此执行计划以t1开头(循环大量行)。 但是在第二个查询中,t2已经有X个记录,这些记录在执行查询的第二部分之前对于引擎是已知的。 因此在该查询中,SQL引擎将使用t2开始执行(SCAN t2因为它很小),并且对于t2中的每个键,它将在t1中执行索引搜索。