Why REPLACE query is taking so much time in SQL Server 2008 - sql-server

I Have a SQL query which converts the date time to 106 format and after that I am replacing the blank space to - which takes too much time almost 4 min while executing . Example as follows
REPLACE(CONVERT(VARCHAR,GETDATE(),106),' ','-') DDate
Output 19-Feb-2015
Without replace my query is taking 0 second
Is there any another way to get the custom format dates as mentioned above ?
I understood that REPLACE will compare the collection of result items.
But it should not take 4 min to replace 100 to 200 data.
Any thoughts?
Query as
SELECT TOP(ISNULL(100,'10000'))
FD.Flight 'Select'
,FD.Filename
,ISNULL(FD.RefNo, 'FLT-' + CONVERT(VARCHAR, FD.FLID)) 'FlightID'
,FD.Registration
,ISNULL(FD.FlightNumber, '') FlightNumber
**,REPLACE(CONVERT(VARCHAR,FD.TKD,106),' ','-') TODate**
,FD.TOGMT
**,REPLACE(CONVERT(VARCHAR,FD.LKD,106),' ','-') LDDate**
,FD.LDGMT
,FD.Origin
,FD.Destination
,FD.Pilot
,FD.CoPilot
**,REPLACE(CONVERT(VARCHAR,FD.DumpDate,106),' ','-') DDate**
,FD.UserName
,FD.FlightCount
,FD.AcVariation
FROM
dbo.vw_FlightDetails FD
LEFT JOIN [dbo].FlightRemark RM ON RM.FlightID = FD.FLID
WHERE
1=1
ORDER BY
FD.TKD DESC
,FD.TOGMT DESC
Bold Area is the problem i am facing

It's hard to tell what's happening here, but you can try this:
select <all your _other_ columns>,
ISNULL(x.RefNo, 'FLT-' + CONVERT(VARCHAR, x.FLID)) FlightID,
REPLACE(CONVERT(VARCHAR, x.TKD, 106),' ','-') TODate,
REPLACE(CONVERT(VARCHAR, x.LKD, 106),' ','-') LDDate,
REPLACE(CONVERT(VARCHAR, x.DumpDate, 106),' ','-') DDate,
from (
SELECT TOP (ISNULL(100,'10000'))
FD.Flight 'Select'
,FD.Filename
,FD.RefNo,
,FD.FLID
,FD.Registration
,ISNULL(FD.FlightNumber, '') FlightNumber
,FD.TKD
,FD.TOGMT
,FD.LKD
,FD.LDGMT
,FD.Origin
,FD.Destination
,FD.Pilot
,FD.CoPilot
,FD.DumpDate
,FD.UserName
,FD.FlightCount
,FD.AcVariation
FROM
dbo.vw_FlightDetails FD
LEFT JOIN [dbo].FlightRemark RM ON RM.FlightID = FD.FLID
WHERE
1=1
ORDER BY
FD.TKD DESC
,FD.TOGMT DESC
) x
basically, bury the query into a subquery, then format the dates only on the resulting rows. I suspect this is happening because of the top() statement... it is probably processing many more rows with the REPLACE than it needs to.

Related

Find the latest entry amongst same number with a Dash?

We have a table that stores a list of all the quotes we have sent out.
Anytime a customer revises the quotes, the system automatically appends a -1 or -2 based on last used number.
As an example
Original Quote Number : 24545
Customer asked for a revision, the quote number is now 24545-1, after sending the quote, we now have a revision again and the Quote is 24545-2 and so on.
I want to run a SQL query that will show them their Top 20 Quotes and incase of revisions, it should show the latest revisions.
Can you please help me?
I have already written a Query that would bring me top 20 quotes for the last 10 days.
SELECT Top 20
EstimateNumber,CustName,JobDescription,TotalSellPrice,EstimateStatus,EstimateDate,CommissionTableA
FROM [Enterprise32].[dbo].[tablename1]
where EstimateDate BETWEEN DATEADD(Day, -10, getdate()) AND GETDATE() AND SalesRepCode = $id And TotalSellPrice > '5000' AND EstimateStatus = 'P'
Order By TotalSellPrice DESC
This makes some assumptions, but I think this might work. If not, sample data and expected result will be invaluable:
USE Enterprise32;
GO
WITH CTE AS(
SELECT V.EstimateNumber,
V.RevisionNumber,
TN1.CustName,
TN1.JobDescription,
TN1.TotalSellPrice,
TN1.EstimateStatus,
TN1.EstimateDate,
TN1.CommissionTableA,
ROW_NUMBER() OVER (PARTITION BY V.EstimateNumber ORDER BY V.RevisionNumber DESC) AS RN
FROM dbo.TableName1 TN1
CROSS APPLY (VALUES(NULLIF(CHARINDEX('-',TN1.EstimateNumber),0)))CI(I)
CROSS APPLY (VALUES(TRY_CONVERT(int,LEFT(TN1.EstimateNumber,ISNULL(CI.I,LEN(TN1.EstimateNumber))-1)),ISNULL(TRY_CONVERT(int,STUFF(TN1.EstimateNumber,1,CI.I,'')),0)))V(EstimateNumber,RevisionNumber)
WHERE TN1.EstimateDate BETWEEN DATEADD(Day, -10, getdate()) AND GETDATE()
AND TN1.SalesRepCode = $id
And TN1.TotalSellPrice > '5000'
AND TN1.EstimateStatus = 'P')
SELECT TOP (20)
EstimateNumber,
RevisionNumber,
CustName,
JobDescription,
TotalSellPrice,
EstimateStatus,
EstimateDate,
CommissionTableA
FROM CTE
WHERE RN = 1;
With some minor changes, it might work, As there is no data sample:
SELECT Top 20
EstimateNumber,CustName,JobDescription,TotalSellPrice,EstimateStatus,EstimateDate,CommissionTableA
FROM [dbo].[tablename1] tt
LEFT JOIN
(
--Top 20 quotes Last EstimateNumber with revision
SELECT T20.RevisionFree_EstimateNumber +
CONVERT(VARCHAR,
MAX(CONVERT(INT,
SUBSTRING(t.EstimateNumber, CHARINDEX('-', EstimateNumber)+1, LEN(EstimateNumber)-CHARINDEX('-', EstimateNumber))))) Last_EstimateNumber
FROM
(
--Top 20 quotes Original EstimateNumber
SELECT DISTINCT Top 20
TotalSellPrice
,SUBSTRING(EstimateNumber, 1, CHARINDEX('-', EstimateNumber)) RevisionFree_EstimateNumber
FROM [dbo].[tablename1]
where EstimateDate BETWEEN DATEADD(Day, -10, getdate()) AND GETDATE() And TotalSellPrice > '5000' AND EstimateStatus = 'P'
Order By TotalSellPrice DESC
)AS T20
LEFT JOIN
(
SELECT *, SUBSTRING(EstimateNumber, 1, CHARINDEX('-', EstimateNumber)) RevisionFree_EstimateNumber
FROM [dbo].[tablename1]
) t
ON T20.RevisionFree_EstimateNumber = t.RevisionFree_EstimateNumber
GROUP BY T20.RevisionFree_EstimateNumber
)LastEN
ON tt.EstimateNumber = LastEN.Last_EstimateNumber

Calculate the datediff() between the date 1 and 2

I need to calculate the datediff from one column where the in time marked with a 1 and the out time marked with a 2. if an employee swiped in and there is no out or out but there was no in i would like it to show as null.
I am not sure how I go about doing this.
SELECT
u.userid
,et.name
,CASE
WHEN scs.FullName is NULL THEN u.name
WHEN scs.FullName is NOT NULL THEN scs.FullName
END AS name
,e.LoggedTime AS SwipeTime
,CASE
WHEN et.name = 'Output On By Door' OR et.name = 'User Granted
Entry To Door Using Reading Device' THEN 1
ELSE 2
END AS SwipeTimeDiff
,d.name AS Door
FROM [Users] AS u
LEFT JOIN [Events] AS e ON e.RecordIndex1=u.UserID
LEFT JOIN [EventTypes] AS et on e.EventTypeID = et.EventTypeID
join .[Doors] AS d ON e.RecordIndex2 = d.DoorID
LEFT join SecurityContractorSignIn as scs on scs.Badge = u.lastname
WHERE LoggedTime > CONVERT(DATE, GETDATE()) and d.doorid in (32, 50, 42, 51, 33)
ORDER BY u.name,e.LoggedTime DESC
I would like to have a computed column with the time difference in days, hours and minutes or null if if there is a missing in(1) or out(2) time.
Well, the DATEDIFF() function is fully explained here and the difference for the specific datepart you want to extract is returned as an integer.
According to your need you may do something like but you will have the information in three (or more - if you want to extend) different columns:
-- Calculate the difference of how many days have passed
SELECT DATEDIFF(DAY, LoginTime, LogoutTime) AS DaysPassed
-- Calculate the difference of how many hours have passed
SELECT DATEDIFF(HOUR, LoginTime, LogoutTime) AS HoursPassed
-- Calculate the difference of how minutes have passed
SELECT DATEDIFF(MINUTE, LoginTime, LogoutTime) AS MinutesPassed
If you want to return a string whether the employee logged out or not you may use something like:
SELECT ISNULL(CONVERT(nvarchar(50), DATEDIFF(MONTH, '2019-01-04', NULL)), 'No logout')

Find out Monthly Percentage in SQL

I am trying to find out monthly percentage (last 12 Months) for the below query
with severity wise, it would be great if anyone could help me out
SELECT Month(a.[Work Initated Date]) AS Month, a.[Initial Severity],
(CAST(Count(a.[Case Number]) AS Decimal(10,1))/ (select CAST(Count(a.[Case Number]) AS Decimal(10,1))
FROM [DSTRINING].[dbo].[SFDC WorkInitiated] (nolock) a
where a.[Initial Severity]='Critical' AND Month(a.[Work Initated Date])=Month(getdate()))*100) AS 'Work Initated%'
FROM [DSTRINING].[dbo].[SFDC WorkInitiated] (nolock) a
where a.[Initial Severity]='Critical' AND Month(a.[Work Initated Date])=Month(getdate()) AND a.[Work Initiated Target Breached]='NO'
Group by Month(a.[Work Initated Date]), a.[Initial Severity]
You can use window functions for this. Your query is a bit hard to follow, but . . .
select Year(wi.[Work Initated Date]) AS yyyy, Month(wi.[Work Initated Date]) AS mm,
wi.[Initial Severity],
count(*) * 100.0/ sum(count(*)) over partition by Year(wi.[Work Initated Date]), Month(wi.[Work Initated Date])) as [Work Initated%]
from [DSTRINING].[dbo].[SFDC WorkInitiated] wi
where wi.[Initial Severity] = 'Critical' and
Month(wi.[Work Initated Date]) = Month(getdate())) and
wi.[Work Initiated Target Breached] = 'NO'
Group by Year(wi.[Work Initated Date]), Month(wi.[Work Initated Date]), wi.[Initial Severity];
Notes:
I included the year along with the month. I just think that is a good practice to avoid unwanted errors.
I changed the table alias to the initials of the table. That makes the query easier to follow.
The window function in the select calculates the ratio you want.
I removed the conversion to decimal(10, 1). I think that confuses the query (although you can add it back in for your output purposes).

Improving the performance of queries using SQL Server 2012?

I have a table which has 13,0000 records, but without indexing and I have written a query which has 4 LEFT OUTER JOINs.
The query is working fine without any issue. My only concern is performance, it's taking 5-10 minutes to give the results. So my question is how can I improve the performance of the query? My second question is do I need to add indexes? If yes, which index should I add, cluster or non cluster?
My query is:
SELECT Z.* FROM
(SELECT
YTD.Specialisation,
YTD.SpecialisationCode,
ROUND(COALESCE(Today.Revenue_Today,0),0)Revenue_Today,
ROUND(COALESCE(MTD.Revenue_MTD,0),0)Revenue_MTD,
ROUND(COALESCE(YTD.Revenue_YTD,0),0)Revenue_YTD,
ROUND(COALESCE(DTD.Revenue_DTD,0),0)Revenue_DTD,
ROUND(COALESCE(Today.Amount1_Today,0),0)Amount1_Today,
ROUND(COALESCE(MTD.Amount1_MTD,0),0)Amount1_MTD,
ROUND(COALESCE(YTD.Amount1_YTD,0),0)Amount1_YTD,
ROUND(COALESCE(DTD.Amount1_DTD,0),0)Amount1_DTD,
ROUND(COALESCE(Today.Amount2_Today,0),0)Amount2_Today,
ROUND(COALESCE(MTD.Amount2_MTD,0),0)Amount2_MTD,
ROUND(COALESCE(YTD.Amount2_YTD,0),0)Amount2_YTD,
ROUND(COALESCE(DTD.Amount2_DTD,0),0)Amount2_DTD,
ROUND(COALESCE(Today.Amount3_Today,0),0)Amount3_Today,
ROUND(COALESCE(MTD.Amount3_MTD,0),0)Amount3_MTD,
ROUND(COALESCE(YTD.Amount3_YTD,0),0)Amount3_YTD,
ROUND(COALESCE(DTD.Amount3_DTD,0),0)Amount3_DTD,
ROUND(COALESCE(Today.Amount4_Today,0),0)Amount4_Today,
ROUND(COALESCE(MTD.Amount4_MTD,0),0)Amount4_MTD,
ROUND(COALESCE(YTD.Amount4_YTD,0),0)Amount4_YTD,
ROUND(COALESCE(DTD.Amount4_DTD,0),0)Amount4_DTD,
ROUND(COALESCE(Today.Amount5_Today,0),0)Amount5_Today,
ROUND(COALESCE(MTD.Amount5_MTD,0),0)Amount5_MTD,
ROUND(COALESCE(YTD.Amount5_YTD,0),0)Amount5_YTD,
ROUND(COALESCE(DTD.Amount5_DTD,0),0)Amount5_DTD
FROM
(select
a.SpecialisationCode,
a.Specialisation,
SUM(a.DoctorFee)Revenue_YTD,
SUM(a.Amount1)Amount1_YTD,
SUM(a.Amount2)Amount2_YTD,
SUM(a.Amount3)Amount3_YTD,
SUM(a.Amount4)Amount4_YTD,
SUM(a.Amount5)Amount5_YTD
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') >= FORMAT((CONVERT(smalldatetime,'2012-04-01',111)),'yyyy-04-01')
AND FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') <= '2012-05-01'
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)YTD
LEFT OUTER JOIN
(select
a.SpecialisationCode,
a.Specialisation,
SUM(a.DoctorFee)Revenue_DTD,
SUM(a.Amount1)Amount1_DTD,
SUM(a.Amount2)Amount2_DTD,
SUM(a.Amount3)Amount3_DTD,
SUM(a.Amount4)Amount4_DTD,
SUM(a.Amount5)Amount5_DTD
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') >= '2012-04-01'
AND FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') <= '2012-05-01'
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)DTD
ON DTD.SpecialisationCode=YTD.SpecialisationCode
LEFT OUTER JOIN
(select
a.SpecialisationCode,
a.Specialisation,
SUM(a.DoctorFee)Revenue_MTD,
SUM(a.Amount1)Amount1_MTD,
SUM(a.Amount2)Amount2_MTD,
SUM(a.Amount3)Amount3_MTD,
SUM(a.Amount4)Amount4_MTD,
SUM(a.Amount5)Amount5_MTD
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') >= FORMAT((CONVERT(smalldatetime,'2012-05-01',111)),'yyyy-MM-01')
AND FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') <= FORMAT((CONVERT(smalldatetime,eomonth('2012-05-01'),111)),'yyyy-MM-dd')
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)MTD
ON YTD.SpecialisationCode=MTD.SpecialisationCode
LEFT OUTER JOIN
(select
a.SpecialisationCode,
a.Specialisation,
COALESCE(SUM(a.DoctorFee),0)Revenue_Today,
SUM(a.Amount1)Amount1_Today,
SUM(a.Amount2)Amount2_Today,
SUM(a.Amount3)Amount3_Today,
SUM(a.Amount4)Amount4_Today,
SUM(a.Amount5)Amount5_Today
from tbl_doctor a
where FORMAT((CONVERT(smalldatetime,a.BillDate,111)),'yyyy-MM-dd') = '2012-05-01'
and a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
GROUP BY a.SpecialisationCode,a.Specialisation)Today
ON YTD.SpecialisationCode=Today.SpecialisationCode ) z
order by z.Specialisation
It looks to me that you can solve the entire query in one pass, by using conditional aggregation.
I haven't used SQL Server that much, so I don't exactly get the date logic, but as I understand you are calculating the amount over different time periods, like accumulated since the start of the year, since the start of the month, and todays amount etcetera.
For such a query, you are anyway touching all records with a BillDate between the start of the year and todays date. You should be able to use a query similar to the below. The idea is to SUM the amount only if the BillDate is in the time period.
select a.SpecialisationCode
,a.Specialisation
,sum(case when a.BillDate = today then a.Amount1 end) as Amount1_Today
,sum(case when a.BillDate between date 'first-day-in-month' and today then a.Amount1 end) as Amount1_MTD
,sum(a.Amount1) as Amount1_YTD
from tbl_doctor
where a.SpecialisationCode!=0
and a.Specialisation NOT IN (' ')
and a.BillDate between date 'first day in year'
and date 'today'
group
by a.SpecialisationCode
,a.Specialisation;
Let me know if you don't get this to work!

in grouping getting duplicate records

I want to filter records on the basis of month. Requirement is in month how much projects are in "completed, pending, started etc" status. This is my query but i am getting duplicate records.
SELECT distinct
convert(varchar(7), w.ExpectedStartDate, 126) AS StatusOfMonth,
COUNT(w.StatusTypeId) AS StatusCount,
w.StatusTypeId,
st.StatusTypeName
FROM Table1 w
LEFT OUTER JOIN StatusType st ON st.StatusTypeId = w.StatusTypeId
WHERE CONVERT(VARCHAR(20), w.ExpectedStartDate, 103) BETWEEN '10/01/2011' AND '14/04/2011'
GROUP BY ExpectedStartDate, w.StatusTypeId, st.StatusTypeName
Please see image to clarify what i want. Please let me know how can i get correct results.
Looks like your grouping by the date, not by the month or by the status of month
Group by
DATEPART(M, ExpectedStartDate)
or
convert(varchar(7), w.ExpectedStartDate, 126)
instead of just ExpectedStartDate
EDIT
In response the comment:
Try getting rid of
convert(varchar(7), w.ExpectedStartDate, 126) AS StatusOfMonth
and just try it like this:
SELECT
convert(varchar, datepart(yyyy, w.ExpectedStartDate)) + '-' + CONVERT(varchar(3), DATENAME(month, w.ExpectedStartDate)),
w.StatusTypeId,
st.StatusTypeName,
COUNT(w.StatusTypeId) AS StatusCount
FROM
Table1 w LEFT OUTER JOIN
StatusType st ON st.StatusTypeId = w.StatusTypeId
WHERE
w.ExpectedStartDate BETWEEN '1/10/2011' AND '04/14/2011'
GROUP BY
datepart(M, w.ExpectedStartDate),
datepart(yyyy, w.ExpectedStartDate),
w.StatusTypeId,
st.StatusTypeName

Resources