Improvise SQL query - sql

I have the below sql which takes 1 or 2 secs to return the result. I am calling this SQL inside cursor for 500 plus times. I am trying to re-write this query.
SELECT Sum(CASE
WHEN UpdatedAdjustedOT IS NOT NULL
AND UpdatedAdjustedOT != ''
AND UpdatedAdjustedOT != '0'
THEN CONVERT(DECIMAL(18, 2), UpdatedAdjustedOT)
ELSE 0
END) AS OTHours
FROM tbl_OTAuthorization
WHERE EmployeeCodeFK = #EmployeeCode
AND month(OTDate) = Month(#FromDate)
AND year(OTDate) = Year(#FromDate)
Please suggest me how do I re-write this query in a better way

Don't filter on function results. Find a way to replace this:
AND month(OTDate) = Month(#FromDate)
AND year(OTDate) = Year(#FromDate)
to something like this:
and OTDate >= the first day of the month for #FromDate
and OTDate < the first day of the month following #FromDate

First, re-write the WHERE clause to look like this:
SELECT . . .
FROM tbl_OTAuthorization
WHERE EmployeeCodeFK = #EmployeeCode AND
OTDate >= DATEADD(day, 1 - DAY(#FromDate), #FromDate) AND
OTDate < DATEADD(month, 1, DATEADD(#FromDate, 1 - DAY(#FromDate), #FromDate));
Second, create an appropriate index for the table:
CREATE INDEX tbl_OTAuthorization_2 ON tbl_OTAuthorization(EmployeeCodeFK, OTDate, UpdatedAdjustedOT);
Third, go back and fix your code so it is not looping over employees and from dates. You should be able to handle the logic in a single query. In general, avoid cursors if you want to optimize the performance of using a database.

Try this:
SELECT Sum(CONVERT(DECIMAL(18, 2), ISNULL(NULLIF(UpdatedAdjustedOT, ''), 0))) as OTHours
FROM tbl_OTAuthorization
WHERE EmployeeCodeFK = #EmployeeCode
AND month(OTDate) = Month(#FromDate)
AND year(OTDate) = Year(#FromDate)

WHERE EmployeeCodeFK = #EmployeeCode
AND OTDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, #FromDate), 0)
AND OTDate < DATEADD(MONTH, 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, #FromDate), 0))

Related

create fiscal week number

How can I put the below logic into a format SQL Server will use to create a fiscal week number ?
if (datepart(week,getdate())-4) <= 0 then (datepart(week,getdate())+49) else (datepart(week,getdate())-4)
The CASE Statement should work:
CASE
WHEN (datepart(week,getdate())-4) <= 0
THEN datepart(week,getdate())+49
ELSE
datepart(week,getdate())-4
END
You could use a case expression:
SELECT CASE WHEN (DATEPART(WEEK, getdate()) - 4) <= 0
THEN DATEPART(WEEK, getdate()) + 49
ELSE DATEPART(WEEK, getdate()) - 4
END
For SQL Server 2012+, you can use IIF
SELECT IIF((datepart(week, getdate())-4) <= 0, datepart(week, getdate()) + 49, datepart(week, getdate()) - 4 )
For Less than SQL Server 2012 version, you may use CASE.

MS SQL Convert date to short

I am trying to get all of the records from a table where the ExpiryDate field is exactly one month away.
The problem however is that the ExpiryDate is stored with the hours, minutes and seconds. How do I therefore say - Get me all of the records from my table where the ExpiryDate (dd/MM/yyyy) is one month ahead of now (dd/MM/yyyy).
This is what I have currently:
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE mt.ExpiryDate = DATEADD(MONTH, 1, GETDATE())
AND mt.IsComplete = 1;
You need some buffertime like
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE mt.ExpiryDate < DATEADD(MONTH, 1, GETDATE())
AND mt.ExpiryDate > DATEADD(DAY, -1, DATEADD(MONTH, 1, GETDATE()))
AND mt.IsComplete = 1;
This will get you all recors that have an expiredate between 1 month ahead an (1 month - 1 day) ahead.
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE mt.ExpiryDate >= DATEADD(DAY, DATEDIFF(DAY, 0, DATEADD(MONTH, 1, GETDATE())), 0)
AND mt.ExpiryDate < DATEADD(DAY, DATEDIFF(DAY, 0, DATEADD(MONTH, 1, GETDATE()) + 1), 0)
AND mt.IsComplete = 1;
I didn't make operation on ExpiryDate as it might be used by an index
Try this:
SELECT * FROM dbo.Custom_MembershipTransaction mt (nolock)
WHERE convert(varchar, mt.ExpiryDate, 102) = convert(varchar, DATEADD(MONTH, 1, GETDATE()),102)
AND mt.IsComplete = 1;

SQL Dynamic Column Reuse

I have the following SQL statement:
Select
DateAdd(month, 1, DateField) as MyNewDate,
CASE WHEN MyNewDate < GetDate() THEN 0 ELSE 1 END as Expired
End
I would like to reuse the calculation in the DateAdd without reevaluating the DateAdd for the Expired column. In reality the query is a lot more complex than this simple dateAdd.
The error I get is :
Invalid column name 'MyNewDate'.
How can I reuse the dynamic column?
You can't use an alias in the same query.
You need something like this
SELECT MyNewDate, CASE WHEN MyNewDate < GetDate() THEN 0 ELSE 1 END as Expired
FROM
(
Select DateAdd(month, 1, DateField) as MyNewDate...
)
or retype it like
Select
DateAdd(month, 1, DateField) as MyNewDate,
CASE WHEN DateAdd(month, 1, DateField) < GetDate() THEN 0 ELSE 1 END as Expired
End
SELECT MyNewDate,
CASE WHEN MyNewDate < GetDate() THEN 0 ELSE 1 END as Expired
(
Select
DateAdd(month, 1, DateField) as MyNewDate
FROM tab
)

how to get records of previous day using tsql?

I need all the records from last day?
Hi
Select * from table1 where tabledate > getdate() -1
with this query, i need to run is exactly after midnight to get exact result. I need to run it in day time and get all the previous day's records.
In SQL Server 2005, this is generally the fastest way to convert a datetime to a date:
DATEADD(day, DATEDIFF(day, 0, yourDate), 0)
In your case, it's done only once, so the how doesn't really matter much. But it does give the following query.
Select
*
from
table1
where
tabledate >= DATEADD(day, DATEDIFF(day, 0, getDate()) - 1, 0)
AND tabledate < DATEADD(day, DATEDIFF(day, 0, getDate()), 0)
Check this page out. It is a great resource for calculating dates.
http://www.simple-talk.com/sql/learn-sql-server/robyn-pages-sql-server-datetime-workbench/#calculatingdates
Another method is to use DATEDIFF alone:
SELECT * FROM table1
WHERE DATEDIFF(DAY, tabledate, GETDATE()) = 1
A datediff of 1 for day covers any time in the previous day.
DECLARE #d SMALLDATETIME;
SET #d = DATEDIFF(DAY, 0, GETDATE());
SELECT <cols> FROM dbo.table1
WHERE tabledate >= DATEADD(DAY, -1, d)
AND tabledate < #d;
Try this:
your_field = cast(dateadd(D,-1,getdate()) as DATE)

composing a SQL query with a date offset

I am trying to do this:
select * from table
where ChangingDate(this is a column which has date and time) = today's date + 1
I am a learner of SQL, and I am bad at date formats. I appreciate if someone can help.
Thank you!
This will return tomorrow's data
WHERE ChangingDate > = dateadd(dd, datediff(dd, 0, getdate())+1, 0)
and ChangingDate < dateadd(dd, datediff(dd, 0, getdate())+2, 0)
This will return today's data
WHERE ChangingDate > = dateadd(dd, datediff(dd, 0, getdate())+0, 0)
and ChangingDate < dateadd(dd, datediff(dd, 0, getdate())+1, 0)
See also How Does Between Work With Dates In SQL Server?
There's a trick with datetimes in databases - you almost never want an = comparison, because as you saw they also include a time component. Instead, you want to know if it falls inside a range that includes the entire day. Sql Server 2008 has a new date type that helps with this, but until you upgrade, do it like this:
WHERE (ChangingDate >= dateadd(dd,1, datediff(dd,0, getDate()))
AND ChangingDate < dateadd(dd,2, datediff(dd,0, getDate())))
You can do an equals comparison if you are certain that all the records have a 0-value (or other known value) for the time component in that column. What you don't want to do is truncate the column, because that means doing extra work per-record (slow) and will break your index (very slow).
select *
from MyTable
where DATEADD(dd, 0, DATEDIFF(dd, 0, ChangingDate)) = SELECT DATEADD(dd, 1, DATEDIFF(dd, 0, GETDATE()))
you may want to try something like
select * from table where columndate=GetDate() + 1
Sounds like you want the DATEPART function to find where the column date has the same year, month, day regardless of time of day:
SELECT * FROM Table
WHERE
DATEPART(Month, Date) = DATEPART(Month, #SomeDate)
AND DATEPART(Day, Date) = DATEPART(Day, #SomeDate)
AND DATEPART(Year, Date) = DATEPART(Year, #SomeDate)
Otherwise, you want to use DateAdd like the other posters.