Related
We have a string field for date of birth and now we have to convert it in order to perform the calculations required. However when we are using CAST or CONVERT to convert to perform the calculations it is not working.
select distinct(ptr.RecordID)
from dbo.PatientRecord as ptr
where
ptr.CHName like 'Access2Loc%'
AND ptr.RecordID
in(
select
(
case when
(DATEDIFF(hour, convert(date,DOB,110), GETDATE())/8766)>18
then PatientID
else NULL
end
) as RecordID
from
PatientView
where ISDATE(DOB) = 1
)
SQL Server considers this a "feature". It is hard to explain, but the where is not necessarily executed before the select.
In SQL Server 2012+, use try_convert() (or try_cast():
where ptr.CHName like 'Access2Loc%' and
ptr.RecordID in (select (case when DATEDIFF(hour, try_convert(date, DOB, 110), GETDATE()) / 8766 > 18
then PatientID
end) as RecordID
from PatientView
where ISDATE(DOB) = 1
)
In more ancient versions, you can use a case expression for much the same effect.
-- this will guarantee that ##t1 contains only valid dob rows
if object_id('tempdb..##t1') is not null
drop table #t1
select * into ##t1 from patientview where isdate(dob)=1
select distinct(ptr.RecordID)
from dbo.PatientRecord as ptr
where
ptr.CHName like 'Access2Loc%'
AND ptr.RecordID
in(
select
(
case when
(DATEDIFF(hour, convert(date,DOB,110), GETDATE())/8766)>18
then PatientID
else NULL
end
) as RecordID
from
##t1
)
drop table ##t1
Okay, so I have kind of a weird issue... the dates in the table have been entered in as string values MMDDYYYY and I'm trying to have the displayed as MM/DD/YYYY in a report and only select the most recent date pertaining to an ID, because some ID's may have multiple dates.
Example of my table:
ID | MyDate |
------+----------+
1 | 01302014 |
1 | 04222014 |
2 | 01302014 |
What I want to see when I select and insert into a temp table is this:
ID | MyDate |
------+-----------+
1 | 4/22/2014 |
2 | 1/30/2014 |
I know that storing dates as string values is a poor practice especially when storing them as MMDDYYYY, but does anyone have a solution to this nightmare?
EDIT
I forgot to mention that some fields might be NULL. Not sure if that makes a difference or not, but I think it does if I try to flip the dates using Right, Left, Convert.
This question is for almost a year ago, nut probably someone can find it useful.
You need to CONVERT your string to DATE format and use a ROW_NUMBER function to window your result set.
Create table
DECLARE #tbl TABLE(Id INT, myDate VARCHAR(8))
Sample data
INSERT #tbl
SELECT 1 , '01302014' UNION ALL
SELECT 1 , '04222014' UNION ALL
SELECT 2 , '01302014'
Query
;WITH C AS(
SELECT ROW_NUMBER() OVER (PARTITION BY Id ORDER BY CONVERT(DATETIME, (SUBSTRING(myDate, 5, 4) + '.' + SUBSTRING(myDate, 1, 2) + '.' + SUBSTRING(myDate, 3, 2)), 101) DESC) AS Rn
,Id
,CAST(CONVERT(DATETIME, (SUBSTRING(myDate, 5, 4) + '.' + SUBSTRING(myDate, 1, 2) + '.' + SUBSTRING(myDate, 3, 2)), 101) AS DATE) AS myDate
FROM #tbl
)
SELECT Id, myDate
FROM C
WHERE Rn = 1
SQLFiddle Demo
Using a CONVERT like the following code snippet will work on any SQL Server regardless of language and/or locale configuration.
DECLARE #OldDate varchar(8);
SELECT #OldDate = '04252012';
SELECT CONVERT(datetime, substring(#OldDate,5,4) + '-' + substring(#OldDate,1,2) + '-' + substring(#OldDate,3,2) + 'T00:00:00')
You could try this:
convert(date,SUBSTRING (MyDate,1,2)+'/'+SUBSTRING (MyDate,3,2)+'/'+SUBSTRING (MyDate,5,4),101)
Select CONVERT(datetime,RIGHT('01302014',4) +
LEFT('01302014',2) +
SUBSTRING('01302014',3,2))
'2014-01-30 00:00:00.000'
;with Cte as (Select Id,CONVERT(datetime,RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)) as sDate, C=ROW_NUMBER()
over(PARTITION By Id Order by MyDate desc)
From #Temp)
select *
from Cte
where C=1
First do a conversion to a datetime datatype, then convert it to a format you wish to:
select id, convert(varchar, max(convert(datetime,right(mydate, 4)+left(mydate,4))), 101)
from #t
group by id
Although I can't understand why would it not suffice to just convert it do datetime and leave the formatting where it belongs, to the client.
Select id,convert(varchar(11),cast(dateValue as Date),101)
From
(
Select id,MAX(cast(MyDate As Date)) as dateValue
From tableName
Group By id
) t
The simplest solution is mySQL str_to_date() function.
STR_TO_DATE(`MyDate`, '%m%d%Y')
This will convert it to a DATETIME which you then format as required
DATE_FORMAT(STR_TO_DATE(`MyDate`, '%m%d%Y'), '%c/%e/%Y')
Complete Query:
Select ID, Case When IsDate(RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)) = 1
THEN Convert(varchar(10), Convert(datetime, RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)), 101)
ELSE Null END AS MyDate FROM YourTable a where Case When IsDate(RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)) = 1
THEN Convert(varchar(10), Convert(datetime, RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)), 101)
ELSE Null END = (Select Max(Case When IsDate(RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)) = 1
THEN Convert(varchar(10), Convert(datetime, RIGHT(MyDate,4)+LEFT(MyDate,2)+SUBSTRING(MyDate,3,2)), 101)
ELSE Null END)
FROM YourTable b
Where a.ID = b.ID
)
This is a modified version from Dimitris Kalaitzis' answer.
First, you will need to convert your MyDate into String. The data for example (01302014) is not treated as a string and the leading zero will be removed when you convert it. Therefore, use CAST to make MyDate as a String and add a leading 0 to it. Then you find the right 8 characters so to get rid of the leading zero for months from Oct to Dec.
Here is the code that should work for you:
CONVERT(Date, SUBSTRING(RIGHT('0' + CAST(MyDate AS VARCHAR(10)), 8), 1, 2) + '/' + SUBSTRING(RIGHT('0' + CAST(MyDate AS VARCHAR(10)), 8), 3, 2) + '/' + SUBSTRING(RIGHT('0' + CAST(MyDate AS VARCHAR(10)), 8), 5, 4), 101)
Hope this helps.
You first have to add the slashes to be able to convert it to a date, use STUFF
Then convert it to a DATE and select the MAX group by ID
Query:
SELECT ID, FORMAT(MAX(CONVERT(DATE,STUFF(STUFF(MyDate,3,0,'/'),6,0,'/'))),'MM/dd/yyyy') AS MyDate FROM TableName
GROUP BY ID
Pretty simple question that I can't quite find the answer for:
Is there a simple and safe† way to cast a varchar to datetime in SQL Server?
† i.e. gracefully handle non-datetime strings with a default datetime value
You can filter your rows using the isdate function. This query returns three rows without any conversion errors:
with v as (
select '20110714' value union all
select '2011-07-15' union all
select '3/22/2011' union all
select 'foo'
)
select cast(value as datetime)
from v
where isdate(value) = 1
Edit
When you want a default vaue (like the current date/time), you could do something like this:
select case when isdate(value) = 1 then cast(value as datetime) else getdate() end
From SQL Server Denali you can use TRY_CONVERT. A case expression is the only safe way in previous versions.
You could try
select cast ('28/08/2006 11:23:25' as datetime)
SELECT * FROM tab_val WHERE (CASE ISDATE(val) WHEN 1 THEN CAST(val As DateTime) ELSE NULL END)
More details in the manual
we can place a check that column have the valid datetime and if not then return nulls not genrating any error.
SELECT CASE ISDATE([YourDate]) WHEN 0
THEN CAST([YourDate] AS DATETIME)
ELSE CAST(NULL AS DATETIME) END AS [Your Date]
FROM [dbo].[yourtable]
For ex:
If we have in table records like:
25/06/2009
28/12/2009
19/02/2010
16/04/2011
20/05/2012
I want to split/select this dates according to 6 month intervals starting from current date.
result should be like:
0-6 month from now: first record
7-12 month from now: second record
...
It will be much apreciated if you make this simple as I made it very stupid and complicated like:
declare variable like t1=curdate()+6
t2=curdate()+12
...
then selected records to fit between curdate() and t1, then t1 and t2 etc.
Thanks,
r.
CORRECTION: Had it backwards, Need to use Modulus, not integer division - sorry...
If MonthCount is a calculated value which counts the number of months since a specific Dec 31, and mod is modulus division (output the remainder after dividing)
Select [Column list here]
From Table
Group By Case When MonthCount Mod 12 < 6
Then 0 Else 1 End
In SQL Server, for example, you could use the DateDiff Function
Select [Column list here]
From Table
Group By Case When DateDiff(month, myDateColumn, curdate) % 12 < 6
Then 0 Else 1 End
( in SQL Server the percent sign is the modulus operator )
This will group all the record into buckets which each contain six months of data
SELECT (DATEDIFF(MONTH, thedate, GETDATE()) / 6) AS semester,
SUM(receipt)
FROM thetable
GROUP BY semester
ORDER BY semester
the key idea is grouping and ordering by the expression that gives you the "semester".
This question really baffled me, cos I couldn't actually come up with a simple solution for it. Damn.
Best I could manage was an absolute bastardization of the following where you create a Temp Table, insert the "Periods" into it, join back to your original table, and group off that.
Assume your content table has the following
ID int
Date DateTime
Counter int
And you're trying to sum all the counter's in six month periods
DECLARE #min_date datetime
select #min_date = min(date) from test
DECLARE #max_date datetime
select #max_date = max(date) from test
DECLARE #today_a datetime
DECLARE #today_b datetime
set #today_a = getdate()
set #today_b = getdate()
CREATE TABLE #temp (startdate DateTime, enddate DateTime)
WHILE #today_a > #min_date
BEGIN
INSERT INTO #temp (startDate, endDate) VALUES (dateadd(month, -6, #today_a), #today_a)
SET #today_a = dateadd(month, -6, #today_a)
END
WHILE #today_b < #max_date
BEGIN
INSERT INTO #temp (startDate, endDate) VALUES (#today_b, dateadd(month, 6, #today_b))
SET #today_b = dateadd(month, 6, #today_b)
END
SELECT * FROM #temp
SELECT
sum(counter),
'Between ' + Convert(nvarchar(10), startdate, 121) + ' => ' + Convert(nvarchar(10), enddate, 121) as Period
FROM test t
JOIN #Temp ht
ON t.Date between ht.startDate AND ht.EndDate
GROUP BY
'Between ' + Convert(nvarchar(10), startdate, 121) + ' => ' + Convert(nvarchar(10), enddate, 121)
DROP TABLE #temp
I really hope someone can come up with a better solution my brain has obviously melted.
Not quite what you're attempting to accomplish, but you could use the DATEDIFF function to distinguish the ranging of each record:
SELECT t.MonthGroup, SUM(t.Counter) AS TotalCount
FROM (
SELECT Counter, (DATEDIFF(m, GETDATE(), Date) / 6) AS MonthGroup
FROM Table
) t
GROUP BY t.MonthGroup
This would create a sub query with an expression that expresses the date ranging group you want. It would then group the sub-query by this date ranging group and you can then do whatever you want with the results.
Edit: I modified the example based on your example.
If you're using SQL Server:
SELECT *,
(
FLOOR
(
(
DATEDIFF(month, GETDATE(), date_column)
- CASE WHEN DAY(GETDATE()) > DAY(date_column) THEN 1 ELSE 0 END
) / 6.0
) * 6
) AS SixMonthlyInterval
FROM your_table
If you're using MySQL:
SELECT *,
(
FLOOR
(
(
((YEAR(date_column) - YEAR(CURDATE())) * 12)
+ MONTH(date_column) - MONTH(CURDATE())
- CASE WHEN DAY(CURDATE()) > DAY(date_column) THEN 1 ELSE 0 END
) / 6.0
) * 6
) AS SixMonthlyInterval
FROM your_table
I need the month+year from the datetime in SQL Server like 'Jan 2008'. I'm grouping the query by month, year. I've searched and found functions like datepart, convert, etc., but none of them seem useful for this. Am I missing something here? Is there a function for this?
select
datepart(month,getdate()) -- integer (1,2,3...)
,datepart(year,getdate()) -- integer
,datename(month,getdate()) -- string ('September',...)
If you mean you want them back as a string, in that format;
SELECT
CONVERT(CHAR(4), date_of_birth, 100) + CONVERT(CHAR(4), date_of_birth, 120)
FROM customers
Here are the other format options
Beginning with SQL Server 2012, you can use:
SELECT FORMAT(#date, 'yyyyMM')
Use:
select datepart(mm,getdate()) --to get month value
select datename(mm,getdate()) --to get name of month
In SQL server 2012, below can be used
select FORMAT(getdate(), 'MMM yyyy')
This gives exact "Jun 2016"
Funny, I was just playing around writing this same query out in SQL Server and then LINQ.
SELECT
DATENAME(mm, article.Created) AS Month,
DATENAME(yyyy, article.Created) AS Year,
COUNT(*) AS Total
FROM Articles AS article
GROUP BY
DATENAME(mm, article.Created),
DATENAME(yyyy, article.Created)
ORDER BY Month, Year DESC
It produces the following ouput (example).
Month | Year | Total
January | 2009 | 2
How about this?
Select DateName( Month, getDate() ) + ' ' + DateName( Year, getDate() )
That format doesn't exist. You need to do a combination of two things,
select convert(varchar(4),getdate(),100) + convert(varchar(4),year(getdate()))
( Month(Created) + ',' + Year(Created) ) AS Date
the best way to do that is with :
dateadd(month,datediff(month,0,*your_date*),0)
it will keep your datetime type
cast(cast(sq.QuotaDate as date) as varchar(7))
gives "2006-04" format
The question is about SQL Server 2005, many of the answers here are for later version SQL Server.
select convert (varchar(7), getdate(),20)
--Typical output 2015-04
SQL Server 2005 does not have date function which was introduced in SQL Server 2008
returns the full month name, -, full year e.g. March-2017
CONCAT(DATENAME(mm, GetDate()), '-', DATEPART(yy, GetDate()))
I had the same problem and after looking around I found this:
SELECT DATENAME(yyyy, date) AS year
FROM Income
GROUP BY DATENAME(yyyy, date)
It's working great!
Converting the date to the first of the month allows you to Group By and Order By a single attribute, and it's faster in my experience.
declare #mytable table(mydate datetime)
declare #date datetime
set #date = '19000101'
while #date < getdate() begin
insert into #mytable values(#date)
set #date = dateadd(day,1,#date)
end
select count(*) total_records from #mytable
select dateadd(month,datediff(month,0,mydate),0) first_of_the_month, count(*) cnt
from #mytable
group by dateadd(month,datediff(month,0,mydate),0)
---Lalmuni Demos---
create table Users
(
userid int,date_of_birth date
)
---insert values---
insert into Users values(4,'9/10/1991')
select DATEDIFF(year,date_of_birth, getdate()) - (CASE WHEN (DATEADD(year, DATEDIFF(year,date_of_birth, getdate()),date_of_birth)) > getdate() THEN 1 ELSE 0 END) as Years,
MONTH(getdate() - (DATEADD(year, DATEDIFF(year, date_of_birth, getdate()), date_of_birth))) - 1 as Months,
DAY(getdate() - (DATEADD(year, DATEDIFF(year,date_of_birth, getdate()), date_of_birth))) - 1 as Days,
from users
Yes, you can use datename(month,intime) to get the month in text.
,datename(month,(od.SHIP_DATE)) as MONTH_
Answer:
MONTH_
January
January
September
October
December
October
September
It's work great.
DECLARE #pYear VARCHAR(4)
DECLARE #pMonth VARCHAR(2)
DECLARE #pDay VARCHAR(2)
SET #pYear = RIGHT(CONVERT(CHAR(10), GETDATE(), 101), 4)
SET #pMonth = LEFT(CONVERT(CHAR(10), GETDATE(), 101), 2)
SET #pDay = SUBSTRING(CONVERT(CHAR(10), GETDATE(), 101), 4,2)
SELECT #pYear,#pMonth,#pDay
The following works perfectly! I just used it, try it out.
date_format(date,'%Y-%c')