converting varchar to date/Using isdate() - sql-server-2005

I have a flat file that I am importing into a SQL Server 2005 staging table as character data.
I need to convert the birthday field to datetime format when copying it to the final destination table. I was doing so using the following:
BIRTHDAY = case when isdate(DOB)=1 then convert(datetime, '19'+right(DOB, 2)+left(DOB, 2)+substring(DOB,3,2)) else null end
The problem is only 100+ of the birthdays from the 32k+ file are identified as dates.
I cannot see a difference between the ones that are dates and the ones that aren't. I have included a sampling below.
good date bad date
41129 100465
10531 122467
10429 20252
81030 62661
31231 20959
11028 91965
80928 60665

Looks like the raw data is in MMDDYY, but the months are not 0-padded.
Building on this assumption, you can parse the date parts like below and rebuild a datetime:
declare #raw table (dob varchar(100));
insert into #raw
select '41129' union all
select '10531' union all
select '10429' union all
select '81030' union all
select '31231' union all
select '11028' union all
select '80928' union all
select '100465' union all
select '122467' union all
select '20252' union all
select '62661' union all
select '20959' union all
select '91965' union all
select '60665'
select *,
[asDate] = dateadd(day, dd - 1, dateadd(month, mm - 1, dateadd(year, ('19' + yy)-1900, 0)))
from ( select dob,
substring(right('0' + dob, 6), 1, 2),
substring(right('0' + dob, 6), 3, 2),
substring(right('0' + dob, 6), 5, 2)
from #raw
) as stage (string, mm, dd, yy);

Related

Stripping date from string, casting to date and checking if equal to today's date

I have a character field representing a date in the following format:
'yyyyMMdd-000000'
I'm not completely sure what the 0's represent, but I'm trying to strip those off then check if the date is the same as today's date:
SELECT
acctnum,
acctname
FROM
[Server].[dbo].[Table1]
Where
CAST(LEFT(myDate,8) AS DATE) = CAST(GetDate() as Date)
When executing that statement I get this error:
Conversion failed when converting date and/or time from character string.
What am I doing wrong and how could I fix this?
Use try_cast() instead:
Where TRY_CAST(LEFT(myDate, 8) AS DATE) = CAST(GetDate() as Date)
Then, you can find the bad data using:
select myDate
from [Server].[dbo].[Table1]
Where TRY_CAST(LEFT(myDate, 8) AS DATE) is null;
You can attempt to find the bad data with something like:
select myDate
from [Server].[dbo].[Table1]
where mydate not like '[12][90][0-9][01][0-9][0-9][1-3][0-9]%'
This doesn't find all bad examples, but if something is glaring it will pop.
declare #table1 table
(
acctnum int,
acctname varchar(10),
myDate varchar(20)
)
insert into #table1(acctnum, acctname, myDate)
values(1, 'A', '20200401-000000'),
(2, 'B', convert(varchar(20), getdate(), 112) + '-000000'),
(3, 'C', convert(varchar(20), getdate(), 112) + '-000000'),
(4, 'D', 'abcd-0000');
select *
from #table1;
select *, case isdate(stuffdate) when 1 then cast(stuffdate as date) end
from
(
select *, stuff(stuff(stuff(myDate, 14, 0, ':'), 12, 0, ':'), 9, 1, ' ') as stuffdate
from #table1
where myDate like convert(varchar(20), getdate(), 112)+'%'
) as t;
select *
from
(
select *, stuff(stuff(stuff(myDate, 14, 0, ':'), 12, 0, ':'), 9, 1, ' ') as stuffdate
from #table1
) as t
where case isdate(stuffdate) when 1 then cast(stuffdate as date) end = convert(varchar(20), getdate(), 112);

Converting a string value into number of days

I have data in a column with values such as 4w4d, 1w0d, 2w5d, 0w6d.
How could I use this data to get the number of days out?
Create Table #temp
(
Data char(4),
ExpectedResult int
)
insert into #temp
(
Data,
ExpectedResult
)
select '4w4d','32'
union all
select '1w0d','7'
union all
select '2w5d','19'
union all
select '0w6d','6'
union all
select '0w5d','5'
union all
select '0w1d','1'
union all
select '0w3d','3'
union all
select '1w6d','13'
You need to parse out the week component and the day component and then convert into the number of days. The following is one way to do this:
-- Find the weeks, multiple by 7
convert(int, substring([Data], 1, charindex('w',[Data])-1))*7
-- Find the days and add on
+ convert(int, substring([Data], charindex('w',[Data])+1, charindex('d',[Data])-charindex('w',[Data])-1))
You can parse the string using string operations:
select convert(int, left(data, 1)) * 7 + convert(int, substring(data, 3, 1))
Here is a db<>fiddle with your sample data.

Number of day Count in every week in every month year wise between 2 dates in sql server

I need to get the date and day count values between two dates.
let's suppose, we want to get the records between 1 july to 5 August.
the output should be like below Table image:
we already know that we have 5 weeks in july month and 1 week in august month for this date range :
let's start with first week to last week :
Try this Goutam Singh. I think daycount should now be 7, 2 using the monday as start of the week.
SELECT
[DYear],
[DMonth],
[Week],
DayCount=COUNT(DISTINCT DayCount),
BillableHour=SUM(BillableHour)
FROM
(
SELECT
[DYear]=(YEAR(Workdate)) ,
[DMonth]=(DATENAME(MONTH, Workdate)) ,
DateNames=datename(dw, Workdate),
[Week]='Week ' + CAST((DATEPART(wk,DATEADD(DAY, -1,Workdate)) - MAX(DATEPART(wk,DATEADD(DAY, -1,Workdate)) )over(partition by (select null))+2) AS varchar(20)),
DayCount= ( WorkDate),
BillableHour=(Convert(DECIMAL(16,2),[Hours]))
FROM
#TempTable
WHERE
Workdate between CONVERT(datetime,#FromDate) and CONVERT(datetime,#ToDate)
)G
GROUP BY
[DYear],
[DMonth],
[Week]
Number of days in a week column is not clear to me. otherwise, below will be the query. Just replace value and date columns with your appropriate column names.
select count(value),month(date),datepart(WEEKDAY,date()) as number of week,date
from t
group by date
#Goutam Singh I have here an updated version. Basically, you need a CTE to build a template table for your query and then do a join depending on what is in the table you want to get the TotalHours. Let me know if that is what you want.
DECLARE #StartDate DATE='20180101'
DECLARE #EndDate DATE='20180901'
DECLARE #Dates TABLE(
Workdate DATE Primary Key
)
DECLARE #TempTable TABLE (Id INT, Hours real, WorkDate DATETIME )
INSERT INTO #TempTable
SELECT 1, 5, '03.05.2018 00:00:00' UNION ALL
SELECT 2, 1.5, '08.05.2018 00:00:00' UNION ALL
SELECT 3, 3, '01.05.2018 00:00:00' UNION ALL
SELECT 4, 0, '04.05.2018 00:00:00' UNION ALL
SELECT 5, 2, '03.05.2018 00:00:00' UNION ALL
SELECT 6, 4, '03.05.2018 00:00:00' UNION ALL
SELECT 7, 2, '05.05.2018 00:00:00' UNION ALL
SELECT 8, 0.5, '08.05.2018 00:00:00' UNION ALL
SELECT 9, 0, '01.05.2018 00:00:00' UNION ALL
SELECT 10, 6, '08.05.2018 00:00:00' UNION ALL
SELECT 11, 8, '02.05.2018 00:00:00' UNION ALL
SELECT 12, 3.5, '09.05.2018 00:00:00' UNION ALL
SELECT 13, 1, '09.05.2018 00:00:00' UNION ALL
SELECT 14, 4, '04.05.2018 00:00:00' UNION ALL
SELECT 15, 1, '03.05.2018 00:00:00' UNION ALL
SELECT 16, 0, '02.05.2018 00:00:00' UNION ALL
SELECT 17, 3, '05.05.2018 00:00:00' UNION ALL
SELECT 18, 0.5, '04.05.2018 00:00:00' UNION ALL
SELECT 19, 2, '09.05.2018 00:00:00' UNION ALL
SELECT 20, 0, '09.05.2018 00:00:00'
--DATEADD(DAY, -1,Workdate)
;WITH Dates AS(
SELECT Workdate=#StartDate,WorkMonth=DATENAME(MONTH,#StartDate),WorkYear=YEAR(#StartDate), WorkWeek=datename(wk, DateAdd(DAY,-1,#StartDate) )
UNION ALL
SELECT CurrDate=DateAdd(DAY,1,Workdate),WorkMonth=DATENAME(MONTH,DateAdd(DAY,1,Workdate)),YEAR(DateAdd(DAY,1,Workdate)),datename(wk, Workdate) FROM Dates D WHERE Workdate<#EndDate ---AND (DATENAME(MONTH,D.Workdate))=(DATENAME(MONTH,D.Workdate))
)
SELECT
WorkMonth,
NumWeek=ROW_NUMBER()OVER(PARTITION BY WorkMonth+cast(WorkYear as varchar(20)) ORDER BY WorkdateStart),
NumDayWeek,
WorkYear,
WorkdateStart,
WorkdateEnd,
TotalHours=SUM(TotalHours)
FROM
(
SELECT
D.Workdate,
D.WorkMonth,
D.WorkYear,
D.WorkWeek,
WorkdateStart=MIN(D.Workdate) over(partition by cast(WorkWeek as varchar(20))+workmonth+cast(WorkYear as varchar(20))),
WorkdateEnd=MAX(D.Workdate) over(partition by cast(WorkWeek as varchar(20))+workmonth+cast(WorkYear as varchar(20))),
NumDayWeek=datediff(day,MIN(D.Workdate) over(partition by cast(D.WorkWeek as varchar(20))+workmonth+cast(WorkYear as varchar(20))),MAX(D.Workdate) over(partition by cast(D.WorkWeek as varchar(20))+workmonth+cast(WorkYear as varchar(20))))+1,
T.TotalHours,
T.DayCount
FROM
Dates D
LEFT JOIN
(
SELECT T.WorkDate, TotalHours=sum(T.Hours), DayCount=sum(case when T.Hours>0 then 1 else 0 end) FROM
#TempTable T
GROUP BY
T.WorkDate
)T ON
T.WorkDate = D.Workdate
)Sub
GROUP BY
WorkMonth,
WorkYear,
WorkdateStart,
NumDayWeek,
WorkdateEnd
ORDER BY
WorkdateStart
option (maxrecursion 0)

Return records less than date

I have a table where 2 columns are called Month and Year and are both INT. I need to return all the records that are less than the date provided.
So if I pass the following parameters #Month = 8 and #Year = 2017, I would like to return all records before August 2017. What is the best way to achieve this?
SELECT * FROM testTable
WHERE year <= #Year AND
month < #Month
is my current SQL. This won't work if I need to display the record that is November 2014
Compare them as dates. Like this:
SELECT * FROM testTable
WHERE DATEFROMPARTS(year, month, 1) <= DATEFROMPARTS(#Year, #Month, 1)
Pass The Parameter as Date. Like
DECLARE #MyDate DATE = '08-01-2014'
Now you can go for either of the below
SELECT
*
FROM YourTable
WHERE CAST(ConCAT([Monnth],'-01-',[Year]) AS DATE) = #MyDate
Or
SELECT
*
FROM YourTable
WHERE [Year] = YEAR(#MyDate)
AND [Month] = MONTH(#MyDate)
You can use DATEPART function of SQL Server
SELECT * FROM testTable
WHERE YEAR<= DATEPART(yy,yourdate) AND
MONTH < DATEPART(mm,yourdate)
It would be better to convert data types and query further.
DECLARE #testtable TABLE (id INT identity(1, 1), name VARCHAR(100), year INT, month INT)
INSERT INTO #testtable (name, year, month)
SELECT 'me', '2014', 10
UNION
SELECT 'you', '2017', 08
UNION
SELECT 'us', '2015', 10
UNION
SELECT 'Him', '2017', 10
UNION
SELECT 'Her', '2018', 1
SELECT *
FROM #testtable
WHERE CONCAT (year, '-', right('00' + cast(Month AS VARCHAR(2)), 2), '-', '01')
< = '2017-08-01'

How can I get the most recent date in SQL?

I want to make a SQL query that gets todays date and the most recent date from a date column. So if I have three records in my database that have the following dates:
March 8, 2012
March 2, 2012
December 8, 2011
I want the SQL query to return all records for March 8, 2012 and March 2, 2012 (most recent date). How can I do this?
I can date today's date using:
CONVERT( varchar(100), DATEADD( DAY, 0, getdate() ), 111)
Thank You
Edit:
Thanks everyone. I just have one more question. I have created two views:
create view with top dates
CREATE VIEW topDates AS
select DISTINCT TOP 3 replace(CONVERT(VARCHAR(20),date,111),'-','/') AS dates from CSAResults.dbo.Details
create view dateTwo
select *
from (select ROW_NUMBER() over (order by dates desc) as srNo, dates
from topDates)
AS employee
WHERE srNo=2
And now I want to select * from my DB where a column is equal to the 'dates' column from the view 'dateTwo'
select buildNumber
from CSAResults.dbo.Details
where buildNumber LIKE '%Main '+ (SELECT dates FROM dateTwo) + '%'
But this returns nothing.
Thanks
You can do the following:
select date
from yourtable
where
(
date = Convert(varchar(10), getdate(), 101)
OR
date IN (SELECT Max(date)
FROM yourtable
WHERE date!= Convert(varchar(10), getdate(), 101))
)
Here is an example script that does what you are asking. It uses a sub-query to select all records with MAX on the date. You would just add an OR to also select items for the current date.
DECLARE #A TABLE
(
part_no VARCHAR(5),
rev CHAR,
on_hand TINYINT,
safety_stock TINYINT,
so_no VARCHAR(5),
so_date DATETIME
)
INSERT #A
SELECT '12345', 'A', 10, 15, 'S1234', '12/14/2009' UNION ALL
SELECT '12345', 'A', 10, 15, 'S1233', '10/01/2009' UNION ALL
SELECT '12345', 'A', 10, 15, 'S1232', '08/02/2009' UNION ALL
SELECT '12346', '', 5, 0, 'S1231', '08/01/2009' UNION ALL
SELECT '12347', '-', 0, 0, 'S1230', '10/20/2009' UNION ALL
SELECT '12347', '-', 0, 0, 'S1229', '07/15/2009'
SELECT * FROM #A AS A
WHERE so_date =
(
SELECT MAX(so_date)
FROM #A AS B
WHERE B.part_no = A.part_no AND B.Rev = A.Rev
)
SELECT *
INTO #TEMP
FROM
(
SELECT GETDATE() DATE_FIELD, 'Blah1...' OTHER_FIELDS
UNION SELECT GETDATE() DATE_FIELD, 'Blah2...' OTHER_FIELDS
UNION SELECT DATEADD(d,-1,GETDATE()) DATE_FIELD, 'Blah3...' OTHER_FIELDS
UNION SELECT DATEADD(d,-1,GETDATE()) DATE_FIELD, 'Blah4...' OTHER_FIELDS
UNION SELECT DATEADD(d,-3,GETDATE()) DATE_FIELD, 'Blah5...' OTHER_FIELDS
) A
SELECT * FROM #TEMP
SELECT * FROM
(
SELECT DATE_FIELD, OTHER_FIELDS,
DENSE_RANK() OVER (ORDER BY DATE_FIELD DESC) _RANK
FROM #TEMP
) A
WHERE A._RANK < 3
For your second question:
select buildNumber
from CSAResults.dbo.Details
inner join dateTwo
on buildNumber LIKE '%Main '+ dateTwo.dates + '%'