SQL Last working day - sql

I have the following query
select Case.casekey, LoginName, startdatedate, SenttoClientDate
from case with (nolock)
where SenttoClientDate = dateadd(day,-1, cast(getdate() as date))
This returns results where {senttoclientdate} = yesterday.
The problem is that if I run this on a Monday I will get Sunday's results, but I want last working day's. So if I run on a Monday, I want the Friday's results.

You can do this way:
WHERE SenttoClientDate = (SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE())))

In where condition use casing as below,
select Case.casekey, LoginName, startdatedate, SenttoClientDate
from case with (nolock)
where SentToClientDate =
case when datepart(dw,getdate()) = 2 then dateadd(day,-3,getdate())
when datepart(dw,getdate()) = 1 then dateadd(day,-2,getdate())
else dateadd(day,-1,getdate())
end

Throw in a case on the datepart
where SentToClientDate =
case when datepart(dw,getdate()) = 2 then dateadd(day,-3,getdate()) -- Monday is day 2, for no reason whatsoever
else dateadd(day,-1,getdate())
end

Can you please try with this, it's very simple and perfect solution:
SELECT Case.casekey, LoginName, startdatedate, SenttoClientDate
FROM case with (nolock)
WHERE SenttoClientDate =
CAST(DATEADD(dd,
CASE WHEN DATEPART(weekday, GETDATE()) = 6 THEN 0
ELSE (6-(DATEPART(weekday, GETDATE())+7)) END, GETDATE()) AS DATE)

Related

MS Sql Server statement inside COUNT

It does work in BigQuery but i do not get what am I doing incorrectly in MS SQL Server;
CASE
WHEN COUNT( RSM.RECEIVED_AT BETWEEN DATEADD(day, -84,UDATE.SQLDate) AND UDATE.SQLDate ) >= 1
AND COUNT(SAL.DATE BETWEEN DATEADD(day, -7, UDATE.SQLDate) AND UDATE.SQLDate) >=2
AND COUNT(SAL.DATE BETWEEN DATEADD(day, -14, UDATE.SQLDate) AND DATEADD(day, -7, UDATE.SQLDate)) >= 2
THEN 'True'
ELSE 'False' END AS AVAILABLE
What is the issue??
Incorrect syntax near ')'.
I suspect what you are after is:
CASE
WHEN COUNT(CASE WHEN RSM.RECEIVED_AT BETWEEN DATEADD(DAY, -84, UDATE.SQLDate) AND UDATE.SQLDate THEN 1 END) >= 1
AND COUNT(CASE WHEN SAL.[DATE] BETWEEN DATEADD(DAY, -7, UDATE.SQLDate) AND UDATE.SQLDate THEN 1 END) >= 2
AND COUNT(CASE WHEN SAL.[DATE] BETWEEN DATEADD(DAY, -14, UDATE.SQLDate) AND DATEADD(DAY, -7, UDATE.SQLDate) THEN 1 END) >= 2 THEN 'True'
ELSE 'False'
END AS AVAILABLE;
As I said in the comments: "You can't have a boolean expression within a COUNT (or any other aggregate function), it requires a scalar expression. "

CASE in WHERE Clause

Below is my current SQL Server 2012 query. Basically I want the information from the last business day, but on Monday, I want it to pull Friday's info instead of Sunday. This is what I have so far in my query but it won't accept it.
USE [LetterGeneration]
SELECT
g.LetterGenerationPrintJobId,
CONVERT(CHAR(12), r.CreatedDate, 101) AS CreatedDate,
YEAR(r.CreatedDate) AS Year,
MONTH(r.CreatedDate) AS Month,
DAY(r.CreatedDate) AS Day,
CASE
WHEN DATEPART(dw, r.CreatedDate) = 1
THEN 1
WHEN DATEPART(dw, r.CreatedDate) = 7
THEN 1
ElSE 0
END AS Weekend,
s.LetterGenerationStatusId AS Status,
COUNT(g.LetterGenerationId) AS LetterCount,
SUM(g.LetterPageCount) AS PageCount,
t.IsLitigationCoverLetterAllowed,
CASE
WHEN g.CarrierTrackingNumber LIKE '%1ZE%'
THEN 1
WHEN g.CarrierTrackingNumber LIKE '921489%'
THEN 2
WHEN g.CarrierTrackingNumber LIKE '917190%'
THEN 2
ELSE 3
END AS CarrierType
FROM
[LetterGenerationTemplateRequest] AS R
INNER JOIN
[LetterGenerationTemplate] AS T ON t.[LetterGenerationTemplateId] = r.LetterGenerationTemplateId
INNER JOIN
LetterGeneration G ON g.LetterGenerationTemplateRequestId = r.LetterGenerationTemplateRequestId
INNER JOIN
LetterGenerationStatus S ON g.LetterGenerationStatusId = s.LetterGenerationStatusId
WHERE
(CASE
WHEN (DATENAME(dw,GETDATE()) = 'Monday')
THEN (DATEDIFF(d, r.CreatedDate, GETDATE()) = 3)
ELSE (DATEDIFF(d, r.CreatedDate, GETDATE()) = 1)
END)
AND t.[TemplateKey] NOT LIKE '%PLTV1%'
AND s.LetterGenerationStatusId = 19
ORDER BY
r.CreatedDate DESC, g.LetterGenerationPrintJobId DESC
What am I missing or misunderstanding about my WHERE clause in order to make it work in the way I'm thinking?
Thanks
Maybe convert to a regular AND/OR?
WHERE (
((DATENAME(dw,GETDATE()) = 'Monday') AND (DATEDIFF(d, r.CreatedDate, GETDATE()) = 3))
OR
(DATEDIFF(d, r.CreatedDate, GETDATE()) = 1)
)
....
What am I missing or misunderstanding about my WHERE clause in order to make it work in the way I'm thinking?
Though you haven't given the error message you're getting, I'm sure it's syntax related because you're putting the test INSIDE the result of the case, not outside it
You're writing:
WHERE CASE WHEN it_is_monday THEN data_date = friday ELSE data_date = yesterday END
You should be writing:
WHERE data_date = CASE WHEN it_is_monday THEN friday ELSE yesterday END
Essentially: you're not supposed to use case/when in a where clause to do your "column = something" comparison and return you true or false, you're supposed to use it to just return the "something" you compare against "column" else in order to get your true or false
The other answers focus on "giving you a working solution"; this answer focuses on telling you what was going wrong with your thought processes re your original query
Here's a simpler example:
--wrong syntax to search a table full of cats (4 legs) and people (2 legs)
WHERE CASE WHEN animal_type = 'cat' THEN legs = 4 ELSE legs = 2 END
--right syntax
WHERE limbs = CASE WHEN animal_type = 'cat' THEN 4 ELSE 2 END
Ignoring holidays for a second, and assuming you have at least one record for every date, something like this should work.
where cast(createdDate as date) =
(select max(createdDate )
from table
where createdDate < cast(getDate() as date
and dateName(dw, createdDate in ('Monday' etc)
)
In order to maintain SARGability(able to do a seek against an index) you want to make sure the table columns in the predicate aren't included in any functions.
The following should work and maintain SARGability...
WHERE
r.CreatedDate = CASE
WHEN DATEPART(dw, getdate) = 2
THEN DATEADD(dd, -3, CAST(GETDATE() AS DATE))
ELSE CAST(GETDATE() AS DATE)
END
HTH,
Jason

SQL IN and NOT IN alternative?

I am trying to find a way to optimize my following SQL query which is taking a long time to run:
(s.StaffID in (Select sch.StaffID From Schedule sch
where sch.AccountID=#AccountID
and sch.Date Between DATEADD(day, -90, #Today) and #Today
and sch.Status<>2))
AND
(s.StaffID Not in (Select sch.StaffID From Schedule sch
where sch.AccountID=#AccountID
and sch.Date Between DATEADD(day, -90, #Today) and #Today
and sch.Status=2))
Can I replace it with another simple query which does less work?
You can use aggregation to combine the two expressions:
s.staffid in
(
select staffid
from schedule
where accountid = #accountid
and date between dateadd(day, -90, #today) and #today
group by staffid
having count(case when status <> 2 then 1 end) > 0
and count(case when status = 2 then 1 end) = 0
)
I'd move this logic into sub-query like this:
select s.StaffID
from StaffID as s inner join (
Select StaffID
From Schedule
where
AccountID=#AccountID and
Date Between DATEADD(day, -90, #Today) and #Today and
group by StaffID
having max(case when Status=2 then 2 else 1 end) = 1
) as t
on (s.StaffID = t.StaffID)
So, condition in having will filter out members who had status==2 in past 90 days

T-SQL Get 3 Month Interval : Trying to count Property_IDs over a close_dt Interval

Trying to count Property_IDs over a close_dt Interval
select distinct pd.state AS StateName, zw.CountyName AS [County Name]
,sum(case when pc.close_dt >= dateName(MM,dateadd(MM,-3,GetDate()))then 1
else 0 end) AS [0-3 Months]
,sum(case when pc.close_dt >= dateName(MM,dateadd(MM,-6,GetDate()))
and pc.close_dt < dateName(MM,dateadd(MM,-3,GetDate())) then
1 else 0 end) AS [3-6 Months]
from resnet_mysql.dbo.property_details pd (Nolock)
join resnet.dbo.ZipCodesView zw (nolock)
on CAST(LEFT(pd.zip, 5) AS varchar) = CAST(zw.ZipCodeID AS varchar)
join resnet_mysql.dbo.property_closings pc (nolock)
on pd.property_id = pc.property_id
group by pd.state, zw.countyName, pc.close_dt
How can I get the 3 month interval from the previous 3 month interval value? So it will be 3-6 months?
I want it to look like this.
But I get this error.
I am thinking you want something like this:
select pd.state AS StateName, zw.CountyName AS [County Name],
sum(case when pc.close_dt >= dateadd(month, -3, GetDate()) then 1
else 0
end) AS [0-3 Months]
sum(case when pc.close_dt >= dateadd(month, -6, GetDate()) and
pc.close_dt < dateadd(month, -3, GetDate())
then 1
else 0
end) AS [3-6 Months]
from resnet_mysql.dbo.property_details pd join
resnet.dbo.ZipCodesView zw
on LEFT(pd.zip, 5) = CAST(zw.ZipCodeID as VARCHAR(5)) join
resnet_mysql.dbo.property_closings pc
on pd.property_id = pc.property_id
group by pd.state, zw.countyName;
Your original code has so many errors, it is hard to list them:
DATENAME() returns a string. Why would you want to compare that to a date?
You are aggregating based on date ranges. You don't want to include the date in the GROUP BY.
LEFT() already returns a string; there is no need to convert it.
You probably don't want to compare a string version of zip code to a numeric id. But if you do, the conversion should specify the length.
WITH (NOLOCK) is not recommended unless you actually know what you are doing.

Returning multiple queries as a single result set against the same database columns

So I am trying to create a report which will give me a count of sales orders and compare them to a previous date ranges. unfortunately I am not sure how to approach returning the results as each of these calculations are ran against the same table column.
Ideally my output would look something like this, including the NULL values
partner Today LastYear TwoYear
------- ------ -------- --------
zzz 10 15 4
yyy 2 4
xxx 3 1 2
I have the basic idea down:
DECLARE #currentDay DATETIME
SET #currentDay = DATEDIFF(day,0,GETDATE()) -- Gives it 00:00:00.000 for time
-- Todays orders
SELECT count(s.po_id) as 'Orders Today',c.tp_name
FROM [EDI_001].[dbo].[303v850h] as s
join [EDI_001].[dbo].[Trade] as c
on s.TP_PartID = c.TP_PartID
where s.ExportDate < #currentDay AND
s.ExportDate > DATEADD(day,-1,#currentDay)
group by c.tp_name
order by c.tp_name;
-- Last Years Day's orders
SELECT count(s.po_id) as 'Orders Today',c.tp_name
FROM [EDI_001].[dbo].[303v850h] as s
join [EDI_001].[dbo].[Trade] as c
on s.TP_PartID = c.TP_PartID
where s.ExportDate < DATEADD(year,-1,#currentDay) AND
s.ExportDate > DATEADD(year, -1,DATEADD(day,-1,#currentDay))
group by c.tp_name
order by c.tp_name;
I'll go ahead and stop there, as you can see the queries are almost identical just changing the date range in the where clause. What I don't know is how to combine the two queries into a single result set. As well, my join does not return the empty sets in either query. I realize that it won't with the current join used, however it hasn't shown in different results with left outer joins either... But realistically one problem at a time and the first step is to get a single result set. Any help would be greatly appreciated.
DECLARE #currentDay DATETIME
SET #currentDay = DATEDIFF(day,0,GETDATE()) -- Gives it 00:00:00.000 for time
SELECT Sum(
CASE
WHEN s.ExportDate Between DATEADD(day,-1,#currentDay) AND #currentDay
THEN 1
ELSE 0
END
) As Today,
Sum(
CASE
WHEN s.ExportDate Between DATEADD(year, -1,DATEADD(day,-1,#currentDay)) AND DATEADD(year,-1,#currentDay)
THEN 1
ELSE 0
END
) As LastYear,
Sum(
CASE
WHEN s.ExportDate Between DATEADD(year, -2,DATEADD(day,-1,#currentDay)) AND DATEADD(year,-2,#currentDay)
THEN 1
ELSE 0
END
) As TwoYear,
c.tp_name
FROM [EDI_001].[dbo].[303v850h] as s
JOIN [EDI_001].[dbo].[Trade] as c
on s.TP_PartID = c.TP_PartID
GROUP BY c.tp_name
ORDER BY c.tp_name;
You are looking for the UNION operator.
It's used to combine the result-set of two or more SELECT statements.
http://www.w3schools.com/sql/sql_union.asp
You can use a conditional aggregate:
SELECT c.tp_name,
Today = COUNT(CASE WHEN s.ExportDate > DATEADD(DAY,-1,#currentDay) THEN s.po_id END),
LastYear = COUNT(CASE WHEN s.ExportDate > DATEADD(YEAR,-1,#currentDay)
AND s.ExportDate < DATEADD(YEAR, -1,DATEADD(DAY, -1, #currentDay))THEN s.po_id END),
TwoYear = COUNT(CASE WHEN s.ExportDate > DATEADD(YEAR,-2, #currentDay)
AND s.ExportDate < DATEADD(YEAR, -2, DATEADD(DAY, -1, #currentDay))THEN s.po_id END),
FROM [EDI_001].[dbo].[303v850h] as s
JOIN [EDI_001].[dbo].[Trade] as c
ON s.TP_PartID = c.TP_PartID
WHERE s.ExportDate < #currentDay AND
s.ExportDate > DATEADD(YEAR, -2, DATEADD(DAY, -1, #currentDay))
GROUP BY c.tp_name
ORDER BY c.tp_name;
So you are essentially moving each of your WHERE clauses to a CASE statement inside the the COUNT, so you will only count records where your criteria is met.