How to reduce execution time of SQL Select Query - sql

TitemName and TshotName is the problem here
SELECT DISTINCT
tJobs.* ,
tCustomer.Name AS Customer_name ,
(SELECT tEmployee.First + ' ' + tEmployee.Last
FROM tEmployee
WHERE tEmployee.EmployeeID = tJobs.AccountExecutiveID) AS AccountExecutive,
(SELECT tEmployee.First + ' ' + tEmployee.Last
FROM tEmployee
WHERE tEmployee.EmployeeID = tJobs.AccountManagerID) AS AccountManager,
dbo.RetrunUserFavourite(tJobs.JobNumber, 33369, 'Employee') AS Favorites,
(SELECT COUNT(*)
FROM tShots
WHERE tShots.JobNumber = tJobs.JobNumber) AS shotcount,
SUBSTRING((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber
+ ', ' + Description
FROM tItems
WHERE tItems.CustomerID = tCustomer.CustomerID
FOR XML PATH('')), 3, 200000) titemName,
SUBSTRING((SELECT ', ' + ArtDirection + ', '
+ REPLACE(CONVERT(VARCHAR(5), AdDate, 110), '-',
'/')
FROM tShots
WHERE tShots.JobNumber = tJobs.JobNumber
FOR XML PATH('')), 3, 200000) TshotName
FROM
tJobs
INNER JOIN
tCustomer ON tCustomer.CustomerID = tJobs.CustomerID
WHERE
tCustomer.CustomerID = 68666

I strongly agree with M Ali's comments. Two points I would make. The first is not with regard to performance. But, instead of substring() use:
STUFF((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description
FROM tItems
WHERE tItems.CustomerID = tCustomer.CustomerID
FOR XML PATH('')
), 1, 1, '') as titemName
That way, you don't need strange, meaningless numbers floating around the code.
Second, you may need indexes. Based on the highlighted performance problems, I would suggest:
tItems(CustomerID)
and:
tshots(JobNumber, ArtDirection, AdDate)

You have awful lot of string manipulation going on is your query, anyway a slightly improved version of your query would look something like...
Select DISTINCT
tJobs.*
, tCustomer.Name AS Customer_name
, AE.First + ' ' + AE.Last AS AccountExecutive
, AM.First + ' ' + AM.Last AS AccountManager
, dbo.RetrunUserFavourite(tJobs.JobNumber,33369,'Employee')AS Favorites
, TS.shotcount
, SUBSTRING(( SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description
FROM tItems
where tItems.CustomerID=tCustomer.CustomerID
FOR XML PATH('')), 3, 200000)titemName
, SUBSTRING(( SELECT ', ' + ArtDirection +', '+REPLACE(CONVERT(VARCHAR(5),AdDate,110), '-','/')
FROM tShots
where tShots.JobNumber=tJobs.JobNumber
FOR XML PATH('')), 3, 200000)TshotName
From tJobs
inner join tCustomer on tCustomer.CustomerID = tJobs.CustomerID
Left join tEmployee AE ON AE.EmployeeID = tJobs.AccountExecutiveID
Left join tEmployee AM ON AM.EmployeeID = tJobs.AccountManagerID
Left join (
SELECT JobNumber , Count(*) shotcount
FROM tShots
GROUP BY JobNumber
) TS ON TS.JobNumber = tJobs.JobNumber
WHERE tCustomer.CustomerID = 68666
A Couple of Pointers:
Having sub-queries in your select statement makes it very inefficient, because the sub-query is executed for each row returned by the outer query, a more sensible way of doing it would be to use joins.
You Also have a call to a User-Defined Scalar function dbo.RetrunUserFavourite() in your select , these scalar UDFs are also performance killers, again the same execution logic is applied here, they are also executed for each row returned by the outer query, a more sensible way would be to put the function logic/code inside a CTE and join your query to that CTE.
These comma delimited lists that you are creating on the fly for last two columns will be slow, maybe an Inline-Table-Valued function can give better performance here.

Related

Issue not getting a result when stuff is used

I am using the stuff function to create an comma separated value
stuff works if I run it alone, but when I use in combination with another column to check against, it is failing.
Is it due to datatype issue?
Here is my code
and cast(verifyemails as varchar(max)) in (select STUFF((SELECT Distinct ',' + '''' + cast(emails as varchar(max)) + '''' from roleslist
left join users on users.fkuserid = roleslist.fkroleuserid
where
and fkUserID = 350
group by emails
FOR XML PATH('')), 1,1,'')
The above does not give the results, even the emails do exists in the table, but the below query is working if I run it alone. Does it have to anything with trim or anything?
select STUFF((SELECT Distinct ',' + '''' + cast(emails as varchar(max)) + '''' from roleslist
left join users on users.fkuserid = roleslist.fkroleuserid
where
and fkUserID = 350
group by emails
FOR XML PATH('')), 1,1,'')
If you're doing an IN you shouldn't bother creating a comma-delimited string. If you use a comma-delimited string you need to use LIKE instead of IN. Should be something like this...
and
(select STUFF((SELECT Distinct ',' + '''' + cast(emails as varchar(max)) + ''''
from roleslist
left join users
on users.fkuserid = roleslist.fkroleuserid
where fkUserID = 350
group by emails
FOR XML PATH('')), 1,1,'') LIKE '%' + cast(verifyemails as varchar(max)) + '%'
Or you could simply remove the comma-delimiting stuff and do this...
and cast(verifyemails as varchar(max)) in
(select cast(emails as varchar(max)) from roleslist
left join users
on users.fkuserid = roleslist.fkroleuserid
where fkUserID = 350
group by emails)

Query Filter based on condition

I have this query (SQL Server 2019) and I actually wanted to add a filter to it to show only items where IssueStatusID = 1 (This column is based on int Data Type)
Can anyone help with this or point me in the right direction?
SELECT ID,
STRING_AGG(TRY_CONVERT(varchar, Issue#, 101) + ': ' + Notes + CHAR(13) + CHAR(10) + CHAR(13), CHAR(10)) WITHIN GROUP (ORDER BY Issue# DESC) AS IssueNotes
FROM (SELECT DISTINCT
ac4.ID,
nd.Notes,
nd.Issue#,
nd.IssueStatusID
FROM dbo.IssueTracking AS nd
INNER JOIN dbo.StatusUpdates AS ac4 ON ac4.ID = nd.ReleaseTrackerID) AS vNotes
GROUP BY ID;
Add the WHERE clause as shown below. The WHERE clause limits the data being returned.
SELECT ID,
STRING_AGG(TRY_CONVERT(varchar, Issue#, 101) + ': ' + Notes + CHAR(13) + CHAR(10) + CHAR(13), CHAR(10)) WITHIN GROUP (ORDER BY Issue# DESC) AS IssueNotes
FROM (SELECT DISTINCT
ac4.ID,
nd.Notes,
nd.Issue#,
nd.IssueStatusID
FROM dbo.IssueTracking AS nd
INNER JOIN dbo.StatusUpdates AS ac4 ON ac4.ID = nd.ReleaseTrackerID
WHERE nd.IssueStatusID = 1
) AS vNotes
GROUP BY ID;

Query database to grab data per unique id

I have a database table with the following information (Don't mind the CreatedDates not matching, this is a testing database table):
I want to be able to create a query to Intents and the respective Transcript based on the ContactId (which there are multiple for one user).
As of right now I was able to accomplish pulling out the Intents by user (distinct) with the following:
SELECT distinct [ContactId],[Intents] =
STUFF((SELECT ' ,' + LTRIM(RTRIM(Intent))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
FOR XML PATH('')), 1, 2, '')
FROM ACCOUNT_DATA a
GROUP BY ContactId;
My desired output would be something like this:
Query => Select all users from the Database (distinct) and return Intents (Distinct) + Transcript data and count of the intents. So like:
d463d996-78cc-428e-8a76-e4875e1c8ff4
RescheudleApt (4) : Reschuedle Appointment, Ok, what date?, Ok, what date?,Ok, what date?
ConfirmAppt (2): Confirm my appointment, ok your appointment has been confirmed
So on and so forth for each ContactId in the table, how would I go about this and am I on the right track?
I know that this would be formatted in different alias tables such as ContactId, Count, Transcript.
Try changing your query like this:
SELECT
ContactId,
Intent + ' (' + CONVERT(VARCHAR,COUNT(Intent)) + ')' as Intents,
[Transcript] = STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '')
FROM
ACCOUNT_DATA a
GROUP BY
ContactId, Intent
ORDER BY
ContactId
Here's a demo
or if you want to concatenate Intent and Transcript
SELECT
ContactId,
Intent + ' (' + CONVERT(VARCHAR,COUNT(Intent)) + ') : ' +
STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '') AS "Intent + Transcript"
FROM
ACCOUNT_DATA a
GROUP BY
ContactId, Intent
ORDER BY
ContactId
Edit: Final Query
SELECT DISTINCT ContactId, [Transcript]=STUFF((SELECT '; ' + IntentTranscript
FROM (
SELECT a.ContactId,
a.Intent + ' (' + CONVERT(VARCHAR,COUNT(a.Intent)) + ') : ' +
STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '') AS "IntentTranscript"
FROM ACCOUNT_DATA a
GROUP BY a.ContactId, a.Intent
) c
WHERE c.ContactId = INNER_ACCOUNT_DATA.ContactId
FOR XML PATH('')), 1, 2, '')
FROM
(
SELECT a.ContactId,
a.Intent + ' (' + CONVERT(VARCHAR,COUNT(a.Intent)) + ') : ' +
STUFF((SELECT ' ,' + LTRIM(RTRIM(b.Transcript))
FROM ACCOUNT_DATA b
WHERE b.ContactId = a.ContactId
AND b.Intent = a.Intent
FOR XML PATH('')), 1, 2, '') AS "IntentTranscript"
FROM ACCOUNT_DATA a
GROUP BY a.ContactId, a.Intent
) AS INNER_ACCOUNT_DATA
ORDER BY ContactId
Here's a demo

TSQL Removing last comma from concatenated string

I've a column with concatenated values, but the string comes with a comma at the end.
How can I remove the last comma on existing values?
SELECT
m.Mais_Id
, m.Outro
(SELECT CAST(emp.First_Name + ' ' + emp.Last_Name + ', ' AS VARCHAR(MAX))
FROM
Patos p
LEFT JOIN
Employee emp
ON
p.Pato_Id = emp.Pato_Id
WHERE
m.Pato_Id = p.Pato_Id
FOR XML PATH ('')
) AS Names
FROM
Mais m
I've this:
Mais_Id Outro Names
0 As Adn Meas, Fjds Poi, Csa Drop,
1 Be
2 Tee As Been,
This is the pretended result:
Mais_Id Outro Names
0 As Adn Meas, Fjds Poi, Csa Drop
1 Be
2 Tee As Been
Most neat way to do this is to use stuff() function:
stuff(
(
select ', ' + cast(emp.First_Name + ' ' + emp.Last_Name as varchar(max))
from Patos as p
left outer join Employee as emp on p.Pato_Id = emp.Pato_Id
where m.Pato_Id = p.Pato_Id
for xml path(''), type
).value('.', 'nvarchar(max)')
, 1, 2, '') as Names
Note it's also safer to get concatenated string with value() function, so if you have special characters like & or < it will be properly shown.
Try this:
SELECT Mais_id, m.Outro, Substring(newColumn, 0, LEN(newColumn) - 1)
FROM (
SELECT
m.Mais_Id
, m.Outro
(SELECT CAST(emp.First_Name + ' ' + emp.Last_Name + ', ' AS VARCHAR(MAX)) as newColumn
FROM
Patos p
LEFT JOIN
Employee emp
ON
p.Pato_Id = emp.Pato_Id
WHERE
m.Pato_Id = p.Pato_Id
FOR XML PATH ('')
) AS Names
FROM
Mais m
)

SQL Removing Duplicate Result with Left Join

I've got code that if pulling info from two different tables, and I'm getting duplicates. I've tried DISTINCT in the SELECT statement, but I get lots of errors "ntext data type cannot be selected as DISTINCT because it is not comparable."
So my next attempt was to try GROUP BY, but I get errors "Column Person.Pers_FirstName is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
So my records have multiple relationship fields, but it's a problem because some records have none, one or more than one relationship (the options are NULL, project engineer, project owner, or project contractor). Current code only shows NULL and Project Engineer, but if there's records with the other two then they are excluded. If I include the other relationship descriptions then I get duplicates.
SELECT
RTRIM(ISNULL(Pers_FirstName, '')) + ' ' + RTRIM(ISNULL(Pers_LastName, '')) AS Pers_FullName,
RTRIM(ISNULL(oppocomp.Comp_PhoneCountryCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_PhoneAreaCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_PhoneNumber, '')) AS Comp_PhoneFullNumber,
RTRIM(ISNULL(oppocomp.Comp_FaxCountryCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_FaxAreaCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_FaxNumber, '')) AS Comp_FaxFullNumber,
RTRIM(ISNULL(Pers_PhoneCountryCode, '')) + ' ' + RTRIM(ISNULL(Pers_PhoneAreaCode, '')) + ' ' + RTRIM(ISNULL(Pers_PhoneNumber, '')) AS Pers_PhoneFullNumber,
RTRIM(ISNULL(Pers_FaxCountryCode, '')) + ' ' + RTRIM(ISNULL(Pers_FaxAreaCode, '')) + ' ' + RTRIM(ISNULL(Pers_FaxNumber, '')) AS Pers_FaxFullNumber,
Opportunity.*, oppocomp.Comp_Name, oppocomp.Comp_Territory, oppocomp.Comp_EmailAddress,
oppocomp.Comp_CompanyId, oppocomp.Comp_SecTerr, oppocomp.Comp_CreatedBy,
oppocomp.Comp_PrimaryUserID, Terr_Caption, Pers_Title, Pers_EmailAddress, Pers_SecTerr,
Pers_CreatedBy, Pers_PersonId, Pers_PrimaryUserID, Chan_Description,
oppocomp.Comp_ChannelID, (Oppo_Base_Currency.Curr_CurrencyID) AS Oppo_WeightedForecast_CID,
Pers_ChannelID ((Oppo_Forecast / Oppo_Forecast_Currency.Curr_Rate) * Oppo_Certainty / 100) AS Oppo_WeightedForecast,
Oppo_PrimaryAccountId AS Acc_AccountId, rend_Notes, renl_description,
relcomp.Comp_Name AS Rela_CompanyName
FROM Opportunity
LEFT JOIN Person ON Oppo_PrimaryPersonID = Pers_PersonID
LEFT JOIN Company AS oppocomp ON Oppo_PrimaryCompanyID = Comp_CompanyId
LEFT JOIN Territories ON Oppo_SecTerr = Terr_TerritoryId
LEFT JOIN Channel ON Chan_ChannelId = Oppo_ChannelId
LEFT JOIN RelatedEntityData ON Oppo_OpportunityId = rend_entity1id
LEFT JOIN RelatedEntityLinks ON rend_relatedentitylinkid = REnL_RelatedEntityLinkID
LEFT JOIN Company AS relcomp ON rend_entity2id = relcomp.Comp_CompanyId
LEFT JOIN Currency Oppo_Forecast_Currency ON Oppo_Forecast_CID = Oppo_Forecast_Currency.Curr_CurrencyID
LEFT JOIN Currency Oppo_Base_Currency
ON Oppo_Base_Currency.Curr_CurrencyID = (
SELECT CAST(CAST(Parm_Value AS NCHAR) AS INTEGER)
FROM Custom_SysParams
WHERE Parm_Name = 'BaseCurrency'
)
WHERE Oppo_Deleted IS NULL
AND (renl_description IS NULL OR renl_description = 'Project Engineer')