我正在调整以下SQL查询
SELECT C.zoneId ,
Count(DISTINCT J.id) ,
Sum(BP.InstalledSubtotal)
FROM cust C
INNER JOIN Jobs J
ON J.CustomerId = C.id
LEFT OUTER JOIN(SELECT DISTINCT GZZ.ZipAndPostalCodeId,
GZZ.GeographicalZoneId,
gz.DEALERId
FROM GeoZip GZZ
INNER JOIN GeographicalZone GZ
ON GZZ.GeographicalZoneId = GZ.Id) CGZ
ON CGZ.ZipAndPostalCodeId = C.PhysicalZipId
AND CGZ.DEALERId = c.DEALERId
INNER JOIN BndProduct BP
ON BP.TableRowId = J.id
AND BP.TableId = 23
AND BP.InstalledSubtotal <> 0
WHERE BP.DateCreated BETWEEN 'Nov 1 2015 12:00AM' AND 'Nov 20 2015 11:59PM'
AND ( Cast(BP.DateCreated AS DATE) <> Cast(J.ContractDate AS DATE)
OR ( Cast(BP.DateCreated AS DATE) = Cast(J.ContractDate AS DATE)
AND BP.EmployeeId <> J.SalesRepId ) )
AND ( BP.EmployeeId <> 0
AND BP.EmployeeId IS NOT NULL )
AND ( J.SalesRepId <> 0
AND J.SalesRepId IS NOT NULL )
AND ( EXISTS (SELECT 1
FROM ServLead ISL
INNER JOIN Appts IA
ON IA.ServiceLeadId = ISL.id
INNER JOIN CalEve IE
ON IE.TableId = 1
AND IE.TableRowId = IA.id
INNER JOIN ApptRst IAR
ON IAR.EventId = IE.id
INNER JOIN Job IJ
ON IJ.AppointmentResultId = IAR.id
AND IJ.id = J.id
WHERE ( ISL.IsTemporary = 0 )
AND ( IA.IsTemporary = 0 )
AND ( IE.IsTemporary = 0 )
AND ( IAR.IsTemporary = 0 ))
OR J.ProductionTypeId = 2 )
AND ( BP.IsDeleted = 0 )
AND ( C.IsTemporary = 0 )
AND ( J.IsTemporary = 0 )
AND ( C.ZoneId = 0
OR 0 = 0 )
AND ( CGZ.GeographicalZoneId = 0
OR 0 = 0 )
AND CASE '0'
WHEN 'STATE' THEN C.PhysicalState
WHEN '' THEN 0
ELSE 0
END LIKE 0
AND C.DEALERId = 23
GROUP BY C.zoneId
请参阅执行计划。
有一个索引扫描。我不知道如何将其改为索引搜索。
我尝试了如下所示的提示。
with (forceseek)
但是当我将普通SQL和SQL的结果与提示进行比较时。正常SQL比带有提示的SQL表现更好。
请提供任何即兴查询的建议。 目前它花了大约5至6秒。我试图把它减少到1-2秒。
@Devart:我已经实现了你的解决方案,但似乎执行时间相同。
请按照要求检查执行计划。
答案 0 :(得分:1)
DECLARE @t TABLE (ID INT PRIMARY KEY)
INSERT INTO @t (ID)
SELECT /*DISTINCT*/ IJ.id
FROM ServLead ISL
JOIN Appts IA ON IA.ServiceLeadId = ISL.id
JOIN CalEve IE ON IE.TableId = 1 AND IE.TableRowId = IA.id
JOIN ApptRst IAR ON IAR.EventId = IE.id
JOIN Job IJ ON IJ.AppointmentResultId = IAR.id
WHERE ISL.IsTemporary = 0
AND IA.IsTemporary = 0
AND IE.IsTemporary = 0
AND IAR.IsTemporary = 0
SELECT C.zoneId,
COUNT(DISTINCT J.id),
SUM(BP.InstalledSubtotal)
FROM cust C
JOIN Jobs J ON J.CustomerId = C.id
--LEFT JOIN (
-- SELECT DISTINCT GZZ.ZipAndPostalCodeId,
-- GZZ.GeographicalZoneId,
-- GZ.DEALERId
-- FROM GeoZip GZZ
-- JOIN GeographicalZone GZ ON GZZ.GeographicalZoneId = GZ.id
--) CGZ ON CGZ.ZipAndPostalCodeId = C.PhysicalZipId
-- AND CGZ.DEALERId = C.DEALERId
JOIN BndProduct BP ON BP.TableRowId = J.id
AND BP.TableId = 23
AND BP.InstalledSubtotal <> 0
WHERE BP.DateCreated BETWEEN '20151101 12:00AM' AND '20151120 11:59PM'
AND (
CAST(BP.DateCreated AS DATE) <> CAST(J.ContractDate AS DATE)
OR (
CAST(BP.DateCreated AS DATE) = CAST(J.ContractDate AS DATE)
AND
BP.EmployeeId <> J.SalesRepId)
)
AND BP.EmployeeId <> 0
AND J.SalesRepId <> 0
AND (EXISTS (
SELECT 1
FROM @t IJ
WHERE IJ.id = J.id
) OR J.ProductionTypeId = 2)
AND BP.IsDeleted = 0
AND C.IsTemporary = 0
AND J.IsTemporary = 0
AND (C.ZoneId = 0 OR 0 = 0)
--AND (CGZ.GeographicalZoneId = 0 OR 0 = 0)
AND C.DEALERId = 23
GROUP BY C.zoneId
OPTION(RECOMPILE)
更新 -
CREATE NONCLUSTERED INDEX ix
ON dbo.ServLead (id) WHERE IsTemporary = 0
GO
CREATE NONCLUSTERED INDEX ix
ON dbo.Appts (ServiceLeadId) INCLUDE(id) WHERE IsTemporary = 0
GO
CREATE NONCLUSTERED INDEX ix
ON dbo.CalEve (TableRowId) INCLUDE(id) WHERE IsTemporary = 0 AND TableId = 1
GO
CREATE NONCLUSTERED INDEX ix
ON dbo.ApptRst (EventId) INCLUDE(id) WHERE IsTemporary = 0
GO
CREATE NONCLUSTERED INDEX ix
ON dbo.Job (AppointmentResultId) INCLUDE(id)
GO
ALTER TABLE dbo.BndProduct
ADD DateCreated_DT AS CAST(DateCreated AS DATE) PERSISTED
GO
ALTER TABLE dbo.Jobs
ADD ContractDate_DT AS CAST(ContractDate AS DATE) PERSISTED
GO
DECLARE @t TABLE (ID INT PRIMARY KEY)
INSERT INTO @t
SELECT /*DISTINCT*/ IJ.id
FROM dbo.ServLead ISL
JOIN dbo.Appts IA ON IA.ServiceLeadId = ISL.id
JOIN dbo.CalEve IE ON IE.TableId = 1 AND IE.TableRowId = IA.id
JOIN dbo.ApptRst IAR ON IAR.EventId = IE.id
JOIN dbo.Job IJ ON IJ.AppointmentResultId = IAR.id
WHERE ISL.IsTemporary = 0
AND IA.IsTemporary = 0
AND IE.IsTemporary = 0
AND IAR.IsTemporary = 0
--OPTION(RECOMPILE)
DECLARE @c TABLE
(
ZipAndPostalCodeId INT,
DEALERId INT,
GeographicalZoneId INT,
PRIMARY KEY (ZipAndPostalCodeId, DEALERId, GeographicalZoneId)
)
INSERT INTO @c (ZipAndPostalCodeId, GeographicalZoneId, DEALERId)
SELECT DISTINCT GZZ.ZipAndPostalCodeId,
GZZ.GeographicalZoneId,
GZ.DEALERId
FROM dbo.GeoZip GZZ
JOIN dbo.GeographicalZone GZ ON GZZ.GeographicalZoneId = GZ.id
SELECT C.zoneId,
COUNT(DISTINCT J.id),
SUM(BP.InstalledSubtotal)
FROM dbo.cust C
JOIN dbo.Jobs J ON J.CustomerId = C.id
LEFT JOIN @c CGZ ON CGZ.ZipAndPostalCodeId = C.PhysicalZipId AND CGZ.DEALERId = C.DEALERId
JOIN dbo.BndProduct BP ON BP.TableRowId = J.id
WHERE BP.DateCreated BETWEEN '20151101 12:00AM' AND '20151120 11:59PM'
AND (
BP.DateCreated_DT <> J.ContractDate_DT
OR (
BP.DateCreated_DT = J.ContractDate_DT
AND
BP.EmployeeId <> J.SalesRepId)
)
AND BP.EmployeeId <> 0
AND BP.TableId = 23
AND BP.InstalledSubtotal <> 0
AND J.SalesRepId <> 0
AND (J.id IN (SELECT t.ID FROM @t t) OR J.ProductionTypeId = 2)
AND BP.IsDeleted = 0
AND C.IsTemporary = 0
AND J.IsTemporary = 0
AND (C.ZoneId = 0 OR 0 = 0)
AND (CGZ.GeographicalZoneId = 0 OR 0 = 0)
AND C.DEALERId = 23
GROUP BY C.zoneId
OPTION(RECOMPILE)