Tune the following query for better performance - sql-server

Please help me to tune this sql server query. Here vcompanyquicksearch is a view on the company table.
What indexes should I create? A sort operation is taking place in the execution plan
which costs 24% i.e.,
[CCEP_DEV].[dbo].[Company].vchContactFirstName Descending,
[CCEP_DEV].[dbo].[Company].iCompanyId Ascending
I don't know why the second sorting is taking place... can anyone suggest why?
select top *
from vCompanyquicksearch
LEFT OUTER JOIN ReferenceParameters r1
on vCompanyquicksearch.iCompanyTypeCode = r1.iParameterId AND
r1.iSiteId =1
LEFT OUTER JOIN ReferenceParameters r2
on vCompanyquicksearch.iCompanySubTypeCode = r2.iParameterId AND
r2.iSiteId =1
LEFT OUTER JOIN ReferenceParameters r3
on vCompanyquicksearch.iPhoneTypeId = r3.iParameterId AND
r3.iSiteId =1
LEFT OUTER JOIN Country c ON
vCompanyquicksearch.chCountryCode = c.chCountryCode AND
ISNULL(vCompanyquicksearch.chCountryCode,'''') <> '''' and
c.iSiteId = 1
LEFT OUTER JOIN Region r ON
vCompanyquicksearch.chCountryCode = r.chCountryCode AND
ISNULL(vCompanyquicksearch.chCountryCode,'''') <> '''' AND
vCompanyquicksearch.chRegionCode = r.chRegionCode AND
ISNULL(vCompanyquicksearch.chRegionCode,'''') <> '''' and
r.iSiteId = 1
where vCompanyquicksearch.isiteid = 1 and vCompanyquicksearch.tirecordstatus = 1 and vCompanyquicksearch.iCompanyId in (
select distinct * from (
select customer_id from csu_customer_policy
inner join csu_policy on csu_policy.policy_number = csu_customer_policy.policy_number
and csu_policy.data_source = csu_customer_policy.data_source
where csu_policy.vehicle_no in(
'sgv3976r')
and csu_customer_policy.delete_status = 0 and csu_customer_policy.site_id = ' 1 '
) yTable
) Order by vchName desc

Try this one -
;WITH cte AS
(
SELECT *
FROM ReferenceParameters r
WHERE r.iSiteId = 1
)
SELECT /*TOP*/ *
FROM (
SELECT *
FROM dbo.vCompanyquicksearch c1 --<-- I think the main problem in this view
WHERE c1.isiteid = 1
AND c1.tirecordstatus = 1
) c1
LEFT JOIN cte r1 ON c1.iCompanyTypeCode = r1.iParameterId
LEFT JOIN cte r2 ON c1.iCompanySubTypeCode = r2.iParameterId
LEFT JOIN cte r3 ON c1.iPhoneTypeId = r3.iParameterId
LEFT JOIN (
SELECT *
FROM dbo.Country c
WHERE c.iSiteId = 1
) c ON c1.chCountryCode = c.chCountryCode
AND ISNULL(c1.chCountryCode, '') != ''
LEFT JOIN (
SELECT *
FROM dbo.Region r
WHERE r.iSiteId = 1
) r ON c1.chCountryCode = r.chCountryCode
AND c1.chRegionCode = r.chRegionCode
AND ISNULL(c1.chCountryCode, '') != ''
AND ISNULL(c1.chRegionCode,'') != ''
WHERE c1.iCompanyId IN
(
SELECT DISTINCT customer_id
FROM dbo.csu_customer_policy p
JOIN dbo.csu_policy pc ON pc.policy_number = p.policy_number
AND pc.data_source = p.data_source
WHERE pc.vehicle_no = 'sgv3976r'
AND p.delete_status = 0
AND p.site_id = ' 1 '
)
ORDER BY vchName DESC
Update:
...
SELECT *
FROM (
SELECT TOP ... *
FROM dbo.vCompanyquicksearch c1
WHERE c1.isiteid = 1
AND c1.tirecordstatus = 1
ORDER BY vchName DESC
) c1
...
WHERE c1.iCompanyId IN
(
SELECT DISTINCT customer_id
FROM dbo.csu_customer_policy p
JOIN dbo.csu_policy pc ON pc.policy_number = p.policy_number
AND pc.data_source = p.data_source
WHERE pc.vehicle_no = 'sgv3976r'
AND p.delete_status = 0
AND p.site_id = ' 1 '
)

Related

SQL Server select condition

I wanted to select count (*) from a table with condition based on type of one filed, consider below code I want something like this in one query:
select
count (*)
from
moniotr as m
case
when m.type = 1
begin
join paramter as p on p.id = m.paramId
where .....
end
when m.type = 2
begin
join aggTable as ag on ag.id = m.addId
where ....
Could you show me how to handle this in one query?
For more clearance, I want the count on monitors for those with type 1 with condition 1 and for type 2 with condition 2 , sum of those counts for two types!
thanks
do as 2 separate query and then union the result
select cnt = sum(cnt)
from
(
select cnt = count(*)
from monitor m
inner join paramter as p on p.id = m.paramId
where m.type = 1
union all
select cnt = count(*)
from monitor m
inner join aggTable as ag on ag.id = m.addId
where m.type = 2
) as d

Subquery returned more than 1 value. Stored

I have this SQL query below
SELECT
CASE
WHEN ISNULL(dbo.EducationalBackground.SchoolId,'') = ''
AND ISNULL(dbo.EducationalBackground.SchoolName,'') <> ''
THEN
(SELECT a.SchoolName
FROM dbo.EducationalBackground AS A
INNER JOIN dbo.PersonEducationalBackground as B ON a.EducationalBackgroundId = b.EducationalBackgroundId
WHERE b.PersonId = #PersonId AND a.EducationalLevelId = 1)
WHEN ISNULL(dbo.EducationalBackground.SchoolId,'') = ''
AND ISNULL(dbo.EducationalBackground.SchoolName,'') = ''
THEN 'N/A'
ELSE
(SELECT dbo.School.SchooldName
FROM dbo.School
INNER JOIN dbo.EducationalBackground ON dbo.School.SchoolId = dbo.EducationalBackground.SchoolId
INNER JOIN dbo.PersonEducationalBackground ON dbo.EducationalBackground.EducationalBackgroundId = dbo.PersonEducationalBackground.EducationalBackgroundId
WHERE dbo.PersonEducationalBackground.PersonId = #PersonId)
END AS SchoolName
FROM
dbo.EducationalBackground
INNER JOIN
PersonEducationalBackground ON dbo.EducationalBackground.EducationalBackgroundId = PersonEducationalBackground.EducationalBackgroundId
INNER JOIN
dbo.Person ON PersonEducationalBackground.PersonId = dbo.Person.PersonId
INNER JOIN
PIMS.Employee ON PIMS.Employee.PersonId = dbo.Person.PersonId
INNER JOIN
dbo.EducationLevel ON dbo.EducationLevel.EducationLevelId = dbo.EducationalBackground.EducationalLevelId
WHERE
dbo.Person.PersonId = #PersonId
AND dbo.EducationalBackground.EducationalLevelId = 1
I got an error above as the title said. If U use SELECT TOP 1 it is running fine but I want to get the data from that query. I have two rows of data so far.
I modified your SQL statement,It possible return different rows from your statement,Can you try it, Checking whether the result your want to get
SELECT case when ISNULL(dbo.EducationalBackground.SchoolId,'') = '' and ISNULL(dbo.EducationalBackground.SchoolName,'') <> '' then
EducationalBackground.SchoolName
WHEN ISNULL(dbo.EducationalBackground.SchoolId,'') = '' and ISNULL(dbo.EducationalBackground.SchoolName,'') = '' then 'N/A'
else School.SchooldName
end as SchoolName
FROM dbo.EducationalBackground
INNER JOIN PersonEducationalBackground on dbo.EducationalBackground.EducationalBackgroundId = PersonEducationalBackground.EducationalBackgroundId
inner JOIN dbo.Person ON PersonEducationalBackground.PersonId = dbo.Person.PersonId
inner JOIN PIMS.Employee ON PIMS.Employee.PersonId = dbo.Person.PersonId
inner JOIN dbo.EducationLevel ON dbo.EducationLevel.EducationLevelId = dbo.EducationalBackground.EducationalLevelId
LEFT JOIN PersonEducationalBackground AS b ON EducationalBackground.EducationalBackgroundId = b.EducationalBackgroundId AND EducationalBackground.EducationalLevelId=1
LEFT JOIN dbo.School ON dbo.School.SchoolId = dbo.EducationalBackground.SchoolId AND PersonEducationalBackground.PersonId = #PersonId
where dbo.Person.PersonId = #PersonId
and dbo.EducationalBackground.EducationalLevelId = 1

How to use multiple values in between clause

Hi all is there any way that i can use multiple values in between clause as
column_name between 0 and 100 or 200 and 300 like this
Any help would be appreciated
here is my query SELECT CASE WHEN ISNUMERIC(value_text) = 1 THEN CAST(value_text AS INT) ELSE -1 END) between 0 and 100
i just want to append multiple values in between clause
This is full query
SELECT ROW_NUMBER() OVER
(
order by Vendor_PrimaryInfo.Vendor_ID asc
)AS RowNumber
, Unit_Table.Unit_title, Vendor_Base_Price.Base_Price, Vendor_Base_Price.showprice, Category_Table.Title, Vendor_Registration.Business_Name,
Vendor_PrimaryInfo.Street_Address, Vendor_PrimaryInfo.Locality, Vendor_PrimaryInfo.Nearest_Landmark, Vendor_PrimaryInfo.City, Vendor_PrimaryInfo.State,
Vendor_PrimaryInfo.Country, Vendor_PrimaryInfo.PostalCode, Vendor_PrimaryInfo.Latitude, Vendor_PrimaryInfo.Longitude, Vendor_PrimaryInfo.ImageUrl,
Vendor_PrimaryInfo.ContactNo, Vendor_PrimaryInfo.Email,Vendor_PrimaryInfo.Vendor_ID
FROM Unit_Table INNER JOIN
Vendor_Base_Price ON Unit_Table.Unit_ID = Vendor_Base_Price.Unit_ID INNER JOIN
Vendor_PrimaryInfo ON Vendor_Base_Price.Vendor_ID = Vendor_PrimaryInfo.Vendor_ID INNER JOIN
Vendor_Registration ON Vendor_Base_Price.Vendor_ID = Vendor_Registration.Vendor_ID AND
Vendor_PrimaryInfo.Vendor_ID = Vendor_Registration.Vendor_ID INNER JOIN
Category_Table ON Vendor_Registration.Category_ID = Category_Table.Category_ID
LEFT JOIN
Vendor_Value_Table ON Vendor_Registration.Vendor_ID = Vendor_Value_Table.Vendor_ID LEFT JOIN
Feature_Table ON Vendor_Value_Table.Feature_ID = Feature_Table.Feature_ID
where Vendor_Registration.Category_ID=5 and Vendor_PrimaryInfo.City='City'
AND(
value_text in('Dhol Wala$Shahnai Wala')
or
(SELECT CASE WHEN ISNUMERIC(value_text) = 1 THEN CAST(value_text AS INT) ELSE -1 END) between 0 and 100
)
You can do this using AND/OR logic
value_text NOT LIKE '%[^0-9]%' and
(
value_text between 0 and 100
Or
value_text between 101 and 200
)
If you don't want to repeat the column name then frame the range in table valued constructor and join with your table
SELECT Row_number()
OVER (
ORDER BY Vendor_PrimaryInfo.Vendor_ID ASC )AS RowNumber,
Unit_Table.Unit_title,
Vendor_Base_Price.Base_Price,
Vendor_Base_Price.showprice,
Category_Table.Title,
Vendor_Registration.Business_Name,
Vendor_PrimaryInfo.Street_Address,
Vendor_PrimaryInfo.Locality,
Vendor_PrimaryInfo.Nearest_Landmark,
Vendor_PrimaryInfo.City,
Vendor_PrimaryInfo.State,
Vendor_PrimaryInfo.Country,
Vendor_PrimaryInfo.PostalCode,
Vendor_PrimaryInfo.Latitude,
Vendor_PrimaryInfo.Longitude,
Vendor_PrimaryInfo.ImageUrl,
Vendor_PrimaryInfo.ContactNo,
Vendor_PrimaryInfo.Email,
Vendor_PrimaryInfo.Vendor_ID
FROM Unit_Table
INNER JOIN Vendor_Base_Price
ON Unit_Table.Unit_ID = Vendor_Base_Price.Unit_ID
INNER JOIN Vendor_PrimaryInfo
ON Vendor_Base_Price.Vendor_ID = Vendor_PrimaryInfo.Vendor_ID
INNER JOIN Vendor_Registration
ON Vendor_Base_Price.Vendor_ID = Vendor_Registration.Vendor_ID
AND Vendor_PrimaryInfo.Vendor_ID = Vendor_Registration.Vendor_ID
INNER JOIN Category_Table
ON Vendor_Registration.Category_ID = Category_Table.Category_ID
LEFT JOIN Vendor_Value_Table
ON Vendor_Registration.Vendor_ID = Vendor_Value_Table.Vendor_ID
LEFT JOIN Feature_Table
ON Vendor_Value_Table.Feature_ID = Feature_Table.Feature_ID
JOIN (VALUES (0, 100),
(101, 200),
(201, 300)) tc (st, ed)
ON Try_cast(value_text AS INT) BETWEEN st AND ed
OR Try_cast(value_text AS VARCHAR(100)) = 'Dhol Wala$Shahnai Wala'
WHERE Vendor_Registration.Category_ID = 5
AND Vendor_PrimaryInfo.City = 'City'
Note : You have stored two different information's in a single column which causes lot of pain when you want to extract the data like this. Consider changing your table structure

SQL Query tuning - MS SQL Server -2012

I am new to sql tuning. I have the following SQL which takes around 15 to 20 seconds to produce the results.
SELECT D.DealerName,
Z.Zone,
C.Id ,
L.Id ,
A.Id ,
L.LeadDate,
LT.LeadType ,
EM.FirstName + ' ' + EM.LastName ,
LS.LeadSource ,
--C.*,
E.Id ,
E.StartDateTime,
0 ,
Chiefed = CASE A.AppointmentTypeId
WHEN 3 THEN 'True'
ELSE ''
END,
9 AS WorkflowPhase
FROM Customers C( NOLOCK )
INNER JOIN Dealers D
ON C.DEALERId = D.Id
INNER JOIN Leads L( NOLOCK )
ON L.CustomerId = C.Id
INNER JOIN Appointments A( NOLOCK )
ON A.LeadId = L.Id
AND ( NOT( A.AppointmentTypeId = 5
OR A.AppointmentTypeId = 6 ) )
JOIN CalendarEvents E( NOLOCK )
ON E.TableId = 1
AND E.TableRowId = A.Id
AND E.IsDeleted = 0
AND Dateadd(hh, #TZO, Getdate()) >= E.StartDateTime
LEFT OUTER JOIN AppointmentResults AR( NOLOCK )
ON AR.EventId = E.Id
LEFT OUTER JOIN LeadSources LS( NOLOCK )
ON LS.Id = L.LeadSourceId
LEFT OUTER JOIN LeadTypes LT( NOLOCK )
ON LT.Id = L.LeadTypeId
LEFT OUTER JOIN Users EM( NOLOCK )
ON EM.Id = E.EmployeeId
LEFT OUTER JOIN Zone Z( NOLOCK )
ON Z.Id = C.ZoneId
WHERE EXISTS(SELECT 1
FROM WorkflowStatus WS( NOLOCK )
WHERE TableId = 1
AND TableRowId = A.Id
AND WorkflowPhaseId = 9
AND IsCompleted = 0
AND IsDeleted = 0)
AND ( EXISTS (SELECT 1
FROM dbo.Uft_userpermissionzonesbyworkflow(#EmployeeId, 9)
WHERE ZoneId = C.zoneid) )
AND EXISTS (SELECT 1
FROM Uft_userenableddealers(#EmployeeId)
WHERE DealerId = C.DealerId)
ORDER BY C.LastName,
C.CompanyName,
C.CompanyContact
I already tuned up to my knowledge but still I can see some index scans. I tried to convert those index scans to index seek but it is not possible due to number of records.
Please refer the screenshot of plan diagram and top operations
Kindly provide any suggestions to improvise this query.
DECLARE #p TABLE (DealerId INT PRIMARY KEY WITH (IGNORE_DUP_KEY=ON))
INSERT INTO #p
SELECT DealerId
FROM dbo.Uft_userenableddealers(#EmployeeId)
DECLARE #z TABLE (ZoneId INT PRIMARY KEY WITH (IGNORE_DUP_KEY=ON))
INSERT INTO #z
SELECT ZoneId
FROM dbo.Uft_userpermissionzonesbyworkflow(#EmployeeId, 9)
SELECT ...
FROM ...
WHERE EXISTS(SELECT 1
FROM WorkflowStatus WS( NOLOCK )
WHERE TableId = 1
AND TableRowId = A.Id
AND WorkflowPhaseId = 9
AND IsCompleted = 0
AND IsDeleted = 0)
AND C.zoneid IN (SELECT * FROM #z)
AND C.DealerId IN (SELECT * FROM #p)
ORDER BY C.LastName,
C.CompanyName,
C.CompanyContact
OPTION(RECOMPILE)
as discussed below Devarts answer here the example with a CTE instead of the declared table variables. I'd assume that the declared TVs are faster due to the key, but the CTE is ad-hoc and - maybe - better integrated. Thx for testing:
;WITH p AS
(
SELECT DealerId
FROM dbo.Uft_userenableddealers(#EmployeeId)
)
,z AS
(
SELECT ZoneId
FROM dbo.Uft_userpermissionzonesbyworkflow(#EmployeeId, 9)
)
SELECT ...
FROM ...
WHERE EXISTS(SELECT 1
FROM WorkflowStatus WS( NOLOCK )
WHERE TableId = 1
AND TableRowId = A.Id
AND WorkflowPhaseId = 9
AND IsCompleted = 0
AND IsDeleted = 0)
AND C.zoneid IN (SELECT ZoneId FROM z)
AND C.DealerId IN (SELECT DealerId FROM p)
ORDER BY C.LastName,
C.CompanyName,
C.CompanyContact
OPTION(RECOMPILE)

Get non duplicate Rows From This Query Without using distinct keyword

I need to filter out distinct rows from below query without using distinct keyword.
So in the CM.PfmFolderMstIpMap Table there are duplicate F.Id's or PMMAP.PfmFolderFK Id's so I want to filter out non-duplicate ones
SELECT F.Id,
F.folderno,
F.folderstatusdate,
(SELECT codedesc
FROM cm.codetable
WHERE id = F.FolderStatusCode) 'FolderStatus',
(SELECT codedesc
FROM cm.codetable
WHERE id = F.FolderLocationCode) 'Location',
F.volume,
F.sdexhibits,
F.cost,
F.remarks
FROM cm.pfmfolder F WITH(nolock)
INNER JOIN cm.pfmfoldermstipmap PMMAP WITH(nolock)
ON PMMAP.pfmfolderfk = F.id
INNER JOIN cm.mstip MST WITH(nolock)
ON MST.id = PMMAP.mstipfk
LEFT JOIN tm.mstirsdmstipmap IRMAP WITH(nolock)
ON IRMAP.mstipfk = MST.id
LEFT JOIN tm.mstirsd IRSD WITH(nolock)
ON IRSD.id = IRMAP.mstirsdfk
LEFT JOIN tm.mstir IR WITH(nolock)
ON IR.id = IRSD.mstirfk
LEFT JOIN tm.mstiabasicmark IABM
ON IABM.basicmarknbr = MST.applnnbr
LEFT JOIN tm.mstia IA
ON IA.id = IABM.mstiafk
WHERE ( #FolderNbr IS NULL
OR F.folderno LIKE + #FolderNbr + '%' )
AND ( #ApplnNbr IS NULL
OR MST.applnnbr LIKE + #ApplnNbr + '%' )
AND ( #IrNbr IS NULL
OR IR.irnbr LIKE + #IrNbr + '%' )
AND ( #IaNbr IS NULL
OR IA.ianbr LIKE + #IaNbr + '%' )
AND ( #FolderStatusCode IS NULL
OR F.folderstatuscode = #FolderStatusCode )
AND ( #FolderLocationCode IS NULL
OR F.folderlocationcode = #FolderLocationCode )
AND ( F.folderstatusdate >= #FolderStatusDateFrom
AND F.folderstatusdate < #FolderStatusDateTo )
AND MST.registrycode = #RegistryCode
AND PMMAP.deletedby IS NULL
As Sam said Distinct is the best option. Otherwise use Group by using all columns
You can use Row_Number feature too
Try this
SELECT * FROM
(
SELECT F.Id,
F.folderno,
F.folderstatusdate,
(SELECT codedesc
FROM cm.codetable
WHERE id = F.FolderStatusCode) 'FolderStatus',
(SELECT codedesc
FROM cm.codetable
WHERE id = F.FolderLocationCode) 'Location',
F.volume,
F.sdexhibits,
F.cost,
F.remarks,
Row_number() OVER(partition BY F.Id ORDER BY (SELECT NULL) ASC) RN
FROM cm.pfmfolder F WITH(nolock)
INNER JOIN cm.pfmfoldermstipmap PMMAP WITH(nolock)
ON PMMAP.pfmfolderfk = F.id
INNER JOIN cm.mstip MST WITH(nolock)
ON MST.id = PMMAP.mstipfk
LEFT JOIN tm.mstirsdmstipmap IRMAP WITH(nolock)
ON IRMAP.mstipfk = MST.id
LEFT JOIN tm.mstirsd IRSD WITH(nolock)
ON IRSD.id = IRMAP.mstirsdfk
LEFT JOIN tm.mstir IR WITH(nolock)
ON IR.id = IRSD.mstirfk
LEFT JOIN tm.mstiabasicmark IABM
ON IABM.basicmarknbr = MST.applnnbr
LEFT JOIN tm.mstia IA
ON IA.id = IABM.mstiafk
WHERE ( #FolderNbr IS NULL
OR F.folderno LIKE + #FolderNbr + '%' )
AND ( #ApplnNbr IS NULL
OR MST.applnnbr LIKE + #ApplnNbr + '%' )
AND ( #IrNbr IS NULL
OR IR.irnbr LIKE + #IrNbr + '%' )
AND ( #IaNbr IS NULL
OR IA.ianbr LIKE + #IaNbr + '%' )
AND ( #FolderStatusCode IS NULL
OR F.folderstatuscode = #FolderStatusCode )
AND ( #FolderLocationCode IS NULL
OR F.folderlocationcode = #FolderLocationCode )
AND ( F.folderstatusdate >= #FolderStatusDateFrom
AND F.folderstatusdate < #FolderStatusDateTo )
AND MST.registrycode = #RegistryCode
AND PMMAP.deletedby IS NULL
) AS T
WHERE RN = 1
Distinct is the best option. Otherwise use Group by using all columns

Resources