---------------------------------- Lead MASTER TABLE
Create table leads
(
pk_lead_id int primary key identity,
lead_name varchar(50),
lead_mobile varchar(50)
)
insert into leads
select 'AK','9876543210'
insert into leads
select 'AK1','9876543210'
--....
insert into leads
select 'AK1000','9876543210'
----------------------------------Lead TRANSACTION TABLE
Create table lead_tr
(
pk_leadtr_id int primary key identity,
fk_lead_id int,
tr_date datetime,
tr_remarks varchar(500)
)
--- For Lead ID 1
insert into lead_tr select 1,GETDATE(),'This is First Transaction'
insert into lead_tr select 1,GETDATE(),'This is Second Transaction'
--...
insert into lead_tr select 1,GETDATE(),'This is Hundredth Transaction'
--- For Lead ID 1000
insert into lead_tr select 2,GETDATE(),'This is First Transaction'
insert into lead_tr select 2,GETDATE(),'This is Second Transaction'
---...
insert into lead_tr select 2,GETDATE(),'This is Hundredth Transaction'
------------------- MY PROC. for Lead Details With Latest STATUS
select * from leads
left join
(
select fk_lead_id,max(pk_leadtr_id) as pk_leadtr_id from lead_tr
group by fk_lead_id
)as ltmin on ltmin.fk_lead_id = pk_lead_id
left join lead_tr as lt on lt.pk_leadtr_id = ltmin.pk_leadtr_id
我的潜在客户表包含大量记录。 并且事务表将为每行引线包含50个事务。 如何避免子查询?如何优化此SP。 我需要改变我的表结构吗?
答案 0 :(得分:0)
首先,您应该在fk_lead_id
上为lead_tr添加索引建议您尝试交叉申请
例如,您可以使用类似于此的内容
select L.*, XL.*
from Leads L
cross apply (
select max(pk_leadtr_id) as tr_id
from lead_tr TR
where TR.fk_lead_id = L.pk_lead_id
) XL
Cross Apply几乎总是我体验中最快的方法
网上有很多交叉应用教程,还有外部应用(对应外连接)
答案 1 :(得分:0)
Mathese F,你怎么能使用union all,union all,union all重复“row count”次来插入一些temp ...然后是一些触发器?拜托......
请不要使用他的任何建议。尝试使用窗口函数来选择最近的子行。
;WITH temp
AS (SELECT ROW_NUMBER() OVER (PARTITION BY tr.fk_lead_id ORDER BY tr.pk_leadtr_id DESC) AS marker,
*
FROM leads AS s
LEFT JOIN lead_tr AS tr
ON tr.fk_lead_id = s.pk_lead_id )
SELECT *
FROM temp
WHERE temp.marker = 1
OR temp.marker IS NULL
ORDER BY pk_lead_id
详细了解窗口函数here或其他任何地方。
答案 2 :(得分:0)
我同意Gary Walker的APPLY逻辑是最好的方法,但我不同意该申请。我认为您的查询应该是:
SELECT *
FROM Leads L
OUTER APPLY
( SELECT TOP 1 *
FROM Lead_tr tr
WHERE tr.fk_lead_id = l.pk_lead_id
ORDER BY tr.pk_leadtr_id DESC
) tr;
<强> Example on SQL Fiddle 强>
这使您可以从Lead_tr
获取所有列,而无需再次加入。
您也可以使用ROW_NUMBER()函数执行此操作,这样您的示例中的逻辑读取次数较少,但在测试时使用APPLY时执行速度始终较慢:
SELECT *
FROM Leads L
LEFT JOIN
( SELECT *, RowNum = ROW_NUMBER() OVER(PARTITION BY tr.fk_lead_id ORDER BY tr.pk_leadtr_id DESC)
FROM Lead_tr tr
) tr
ON tr.fk_lead_id = l.pk_lead_id
AND tr.RowNum = 1;
<强> Example on SQL Fiddle 强>
应用强>
(3行受影响)
表'lead_tr'。扫描计数1,逻辑读取7,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
表'线索'。扫描计数1,逻辑读取2,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
SQL Server执行时间:CPU时间= 0毫秒,已用时间= 48毫秒。
<强> ROW_NUMBER 强>
(3行受影响)
表'lead_tr'。扫描计数1,逻辑读取2,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
表'线索'。扫描计数1,逻辑读取2,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
SQL Server执行时间:CPU时间= 0毫秒,已用时间= 146毫秒。
N.B两个查询都在一个热缓存上运行,因此两者的编译时间都是0ms,因此不包含在上面。
在您的实际数据中,您可能会得到不同的结果,因此一如既往地测试您的数据并选择最适合您的方法。
答案 3 :(得分:-1)
我首先建议使用union而不是这个。
例如:
insert into leads
select 'AK','9876543210'
union
select 'AK1','9876543210'
union
select 'AK1000','9876543210'
一个操作而不是一个操作将花费成本。
这些价值来自哪里?
然后你可以想象有一个触发器,它将具有创建事务的小好处。即使不在sp中也适用
50是固定的吗?它们是如何创建的?
你能想象在这里的第一个表和另一个表之间进行连接以插入它们吗?
至少你总会有2个插入(可能带有输出子句,它可能很好)
<强>更新强>
以下是输出示例:
declare @test table (i int)
declare @test2 table (i int, dada date )
insert into @test
output inserted.*, GETDATE() into @test2
values (1)
select * from @test
select * from @test2
我的执行计划只显示一个查询而不是2,所以我认为如果可能的话会更好。