IIF Conditional StartDate EndDate int/date collision - tsql

I am trying to use the IIF statements in SS-2012
I have this which works fine
SELECT
NULLIF(IIF( a.EndDate is null
, DATEDIFF(MONTH, a.StartDate, getdate()) ,
IIF( a.EndDate is not null
, DATEDIFF(MONTH, a.StartDate, a.EndDate) , '')),'')
AS Months
,NULLIF(IIF( a.EndDate is null
, DATEDIFF(Day, a.StartDate, getdate()) ,
IIF( a.EndDate is not null
, DATEDIFF(Day, a.StartDate, a.EndDate) , '')),'')
AS DateDays
FROM
TableDates a
The problem I came across is if the start date and enddate are on the same date(I am trying to default it to 1 month and 30 or 31 days whatever month it is)
I am gettiing
int is incompatible with date
When trying this below
,NULLIF(
IIF ( (a.EndDate is null) , DATEDIFF(Day, a.StartDate, getdate()) ,
IIF ( (a.StartDate = a.EndDate)
, DATEADD(Day, DATEDIFF(Day, a.StartDate, a.EndDate), a.EndDate),
IIF ( (a.EndDate is not null) , DATEDIFF(Day, a.StartDate, a.EndDate),'')
)),'')
How can I default the days to 30-31 and month to 1 if the dates are the same?

If you need to show the number of days of the month as default where start date and enddate are on the same date then i hope the below query will work for you
IIF ( (a.StartDate = a.EndDate),
(datediff(day, a.StartDate, dateadd(month, 1, a.StartDate))),...
and to show the month as default where start date and enddate are on the same date
IIF ( (a.StartDate = a.EndDate),Month(a.StartDate),...

Related

T-SQL Retrieve Last 6 Weeks Data to the Previous Saturday

SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= DATEADD(ww, -6, (Select MAX([TradingDate]) From FactSalesDetail))
ORDER BY TradingDate
Can anyone advise how I can convert the above WHERE Clause from retrieving the last 6 weeks data from Max Date in my Fact Table to the last 6 weeks to the Previous Saturday?
So as of Today that would Saturday 1st Jan and then back 6 weeks from that?
Using the current weekday can get you last Saturday.
And if you bring ##DATEFIRST into the equation then it won't depend on the DATEFIRST setting.
SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())))
AND TradingDate <= CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))
ORDER BY TradingDate
Test snippet for date range
SET DATEFIRST 7;
SELECT
datename(weekday, date_now) AS weekday_now, date_now
, datename(weekday, date1) AS wd1, date1
, datename(weekday, date2) AS wd2, date2
FROM
(
SELECT
CAST(GETDATE() AS DATE) AS date_now
, CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))) AS date1
, CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())) AS date2
) q
weekday_now
date_now
wd1
date1
wd2
date2
Tuesday
2022-01-04
Saturday
2021-11-20
Saturday
2022-01-01
db<>fiddle here

datediff between sets of dates

For some reason I am struggling with the logic of what I am trying to achieve here and was wondering if any help would be forthcoming.
Please find code for the data below -
/****** Object: Table [dbo].[temp_TEST] Script Date: 09/07/2021 12:01:26 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[temp_TEST](
[TransactionId] [int] NULL,
[DateFrom] [datetime] NULL,
[DateTo] [datetime] NULL,
[totalvalue] [decimal](18, 2) NULL,
[DailyAmount] [decimal](18, 2) NULL,
[EffectiveFromDate] [datetime] NULL,
[EffectiveToDate] [datetime] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[temp_TEST] ([TransactionId], [DateFrom], [DateTo], [totalvalue], [DailyAmount], [EffectiveFromDate], [EffectiveToDate]) VALUES (809228, CAST(N'2021-06-14T00:00:00.000' AS DateTime), CAST(N'2021-06-27T00:00:00.000' AS DateTime), CAST(159.16 AS Decimal(18, 2)), CAST(11.37 AS Decimal(18, 2)), CAST(N'1946-01-01T00:00:00.000' AS DateTime), CAST(N'2021-06-22T00:00:00.000' AS DateTime))
INSERT [dbo].[temp_TEST] ([TransactionId], [DateFrom], [DateTo], [totalvalue], [DailyAmount], [EffectiveFromDate], [EffectiveToDate]) VALUES (809228, CAST(N'2021-06-14T00:00:00.000' AS DateTime), CAST(N'2021-06-27T00:00:00.000' AS DateTime), CAST(159.16 AS Decimal(18, 2)), CAST(11.37 AS Decimal(18, 2)), CAST(N'2021-06-23T00:00:00.000' AS DateTime), CAST(N'2021-07-09T11:59:40.833' AS DateTime))
What I am trying to do is work out the number of days that have past between a set of dates.
So what this shows is a DateFrom and DateTo field. These are the keys dates that I want to calculate between the EffectiveFromDate and EffectiveToDate.
So what I would expect is the number of days that past between the DateFrom and DateTo....during the EffectiveFromDate and EffectiveToDate, so how many days per row have past but ONLY during the DateFrom and DateTo date.
First row - has been effective since 01/01/1946, but it ended on the 22/06/21 -that is 9 days between the DateFrom and DateTo dates. That is the 14/06 to the 22/06.
Second row - has been effective since 23/06. It's still effective hence the effectivetodate being today's date...but it's been that value since the 23/06, so that will be 5 days between the DateFrom and DateTo. Including the 23/06.
Hope I've explained myself properly.
Please check below, it should help.
You need to use ISNULL and DATEDIFF functions
SELECT DATEDIFF(day, '2021/08/25', ISNULL('2021/08/28', getdate())) AS DateDiff;
SELECT DATEDIFF(day, '2021/08/25', ISNULL(null, GETDATE())) AS DateDiff;
SELECT DATEDIFF(day, EffectiveFromDate, ISNULL(EffectiveToDate, GETDATE())) AS DateDiff
FROM YourTable
Based on new information in question, please play around with below case when query
SELECT DATEDIFF(day,
case when EffectiveFromDate > DateFrom then EffectiveFromDate else DateFrom end,
case when EffectiveToDate < DateTo then EffectiveToDate else DateTo end) AS DateDiff
FROM temp_TEST
it actually gives you 8 and 4 days, not 9 and 5 but this is how this function works, you can add +1 to include second date in counting, see below
SELECT DATEDIFF(day,
case when EffectiveFromDate > DateFrom then EffectiveFromDate else DateFrom end,
case when EffectiveToDate < DateTo then EffectiveToDate + 1 else DateTo + 1 end) AS DateDiff
FROM temp_TEST

Build the calendar table for current year including weeknum divided to semester

for the below query i need divide the semesters starting from 1 to 26 .. first semester as 1 to 26 weeks and first semester should start from again 1 to 26
Any help is greating appreciated
DECLARE #StartDate DATETIME
DECLARE #CutoffDate DATETIME
SET #StartDate = Dateadd(yy, Datediff(yy, 0, Getdate()), 0)
SET #CutoffDate = Dateadd(yy, Datediff(yy, 0, Getdate()) + 1, -1)
SELECT day,
[week nu],
semester,
[semester week nu]
INTO #currentdates
FROM (SELECT Day = Dateadd(day, rn - 1, #StartDate),
Datepart(week, Dateadd(day, rn - 1, #StartDate)) [Week nu],
CASE
WHEN Month(Dateadd(day, rn - 1, #StartDate)) <= 6 THEN
'First Semester'
ELSE 'Second Semester'
END AS Semester,
Datepart(week, Dateadd(day, rn - 1, #StartDate)) AS
[Semester Week nu]
FROM (SELECT TOP (Datediff(day, #StartDate, #CutoffDate)) rn =
Row_number()
OVER (
ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]) AS x) AS y;
I've got a couple of changes, first, you need to add 1 to your last datediff, your last date was December 30, not 31!
Second of all, I just get the date and week number in the first subselect, and then use these ine case statements for the select
The semester number is if week nu<=26,
The semester week nu is week nu if week nu<=26 else wwek nu -26
DECLARE #StartDate datetime DECLARE #CutoffDate datetime
SET #StartDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
SET #CutoffDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) + 1, -1)
SELECT DAY,
[Week nu],
case when [Week nu]<=26 then 'First Semester' Else 'Second Semester' end Semester,
case when [Week nu]<=26 then [Week nu] Else [Week nu]-26 end[Semester Week nu]
INTO #currentDates
FROM
(SELECT DAY = DATEADD(DAY, rn - 1, #StartDate),
DATEPART(WEEK,DATEADD(DAY, rn - 1, #StartDate)) [Week nu]
FROM
(SELECT TOP (DATEDIFF(DAY, #StartDate, #CutoffDate)+1) rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]) AS x) AS y;

T-SQL Date Function

I have a T-SQL script that runs every weekday. The script does a lookup for new customers in the past 24 hours, with the exceptionof Monday it will do a lookup in the past 72 hours (Friday through Sunday)
Select FirstName, LastName, CustomerID, Date
FROM Customers
WHERE
(
(
DATEPART(WEEKDAY, GetDate())=2 AND
DATEDIFF(DAY, Customers.Date, GetDate()) <= 3 AND
DATEDIFF(DAY, Customers.Date, GetDate()) >= 1
)
OR DATEDIFF(DAY, Customers.Date, GetDate()) = 1
)
I need to change this to do a lookup 30 days prior instead.
ANy ideas? Thanks.
WHERE DATEDIFF(DAY, Customers.Date, GetDate()) <= 30

Understanding TSQL Coalesce function

I am trying to select all 12 months / year. And I thought following TSQL code would do this. However, this does not include all months like I want. What is the cause of this? This is modified code:
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
)
select yt.DateClosed 'r2', m.m 'r3',
month(coalesce(yt.DateClosed, m.m)) as 'MonthClosed',
year(coalesce(yt.DateClosed, m.m)) as 'YearClosed'
from months m
left join yourTable yt
on
( datepart(year, yt.DateClosed) = DATEPART(year, m.m)
and datepart(month, yt.DateClosed) = DATEPART(month, m.m)
or
datepart(year, yt.DateOpened) = DATEPART(year, m.m)
and datepart(month, yt.DateOpened) = DATEPART(month, m.m)
)
AND year(coalesce(yt.DateClosed, m.m)) = 2010
order by yt.DateClosed
So above query does not return all months. But if I change above WHERE lines to:
FROM [PROC].ALL_AUDIT
WHERE
BTK_CLOSED_DATE < #TheMonthLastDate
then this query does return all 12 months. How can this be?
Output that I want and that I see when WHERE is BTK_CLOSED_DATE < #TheMonthLastDate:
r2 r3 MonthClosed YearClosed
NULL 2010-06-01 00:00:00.000 6 2010
NULL 2009-11-01 00:00:00.000 11 2009
2010-01-06 20:02:19.127 2010-01-01 00:00:00.000 1 2010
2010-01-27 23:13:45.570 2010-01-01 00:00:00.000 1 2010
2010-02-15 14:49:14.427 2010-02-01 00:00:00.000 2 2010
2010-02-15 14:49:14.427 2009-12-01 00:00:00.000 2 2010
But if I instead use WHERE:
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
then I see:
r2 r3 MonthClosed YearClosed
NULL 2010-10-01 00:00:00.000 10 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-08-01 00:00:00.000 8 2010
NULL 2010-08-01 00:00:00.000 8 2010
...
So notice that in first result I see NULL for June 2010, which is what I want.
I think the problem has something to do with the fact that my data contains 2009-2011 data, but I only compare months and not years. How would I add in this additional logic?
The only place where you are reducing the data is with the WHERE clause you have already identified. Therefore, the reason you are not getting all the months you expect is down to the column TSK_START_DATE not being less than #TheMonthLastDate for all months.
To prove this hypothesis, run the following section of your query (I have commented out part of the where clause and removed everything under 'yourTable' cte). The results should show you what is being returned in the TSK_Start_Date column for your missing months and help you identify why the rows are missing when applying the < #TheMonthLastDate clause.
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
--TSK_START_DATE < #TheMonthLastDate
)
)
select * , #TheMonthLastDate TheMonthLastDate from yourTable