I have a table of transactions in SQL Server 2016 with a column called mthweekyr
where each row in this column has as a string, the month number, week number of the month, and year of the transaction, where week number is determined by day of the month / 7.
For example, if the transaction date was: 2018-09-28
, this would appear as 9-4-2018
.
The problem is that the original transaction date column is not actually in the table, and I would like to sort these transactions by the mthweekyr
column, but am unable to do so because this column is not a date type, it is a string type. (I don't make the tables, I just use them!)
Any suggestions on how to proceed?
Thanks.
Here's another way...
declare @table table(mthweekyr varchar(10))
insert into @table
values
('9-4-2018'),
('8-4-2018'),
('9-5-2018'),
('7-5-2018'),
('7-4-2018'),
('9-5-2017'),
('9-4-2017')
select *
from @table
order by
cast(right(mthweekyr,4) as int) --order by year first
,cast(left(mthweekyr,charindex('-',mthweekyr)-1) as int) --order by month. Works for single or double digit months
,left(right(mthweekyr,6),1) --order by week number which is always a single digit, since it's the week number of the month not the year.
Late answer , but perhaps a thinner alternative.
You can simply use the implicit conversion of mdy to date
Example
declare @table table(mthweekyr varchar(10))
insert into @table
values
('9-4-2018'),
('8-4-2018'),
('9-5-2018'),
('7-5-2018'),
('7-4-2018'),
('9-5-2017'),
('9-4-2017'),
('10-4-2017'), -- added 2 digit month
('10-5-2017') -- added 2 digit month
Select *
From @table
Order By convert(date,mthweekyr)
Returns
mthweekyr
9-4-2017
9-5-2017
10-4-2017
10-5-2017
7-4-2018
7-5-2018
8-4-2018
9-4-2018
9-5-2018
Using JNevill's suggestion you could leverage PARSENAME for this.
declare @Date varchar(20) = '9-4-2018'
select PARSENAME(replace(@Date, '-', '.'), 1) + '-' + right('00' + PARSENAME(replace(@Date, '-', '.'), 3), 2) + '-' + right('00' + PARSENAME(replace(@Date, '-', '.'), 2), 2)
This returns 2018-09-04
You could also do some string manipulation but that starts to get rather tedious.
obviously not the most efficient I'm sure but to brute force it...
order by substring(@theStr, len(@theStr) - 4 + 1, 4)
+ substring(@thestr, charindex('-',@Thestr)+1,1)
+ right('00' + substring(@thestr, 1, charindex('-',@Thestr)-1),2)
here's how to get there by pieces:
declare @thestr varchar(255) = '9-4-2018'
Declare @SortStr as Varchar(255)
--year
Select @SortStr = substring(@theStr, len(@theStr) - 4 + 1, 4)
print @Sortstr
--day
Select @SortStr = right('00' + substring(@thestr, 1, charindex('-',@Thestr)-1),2)
print @sortStr
--week
Select @SortStr = substring(@thestr, charindex('-',@Thestr)+1,1)
print @sortStr
Select @SortStr = substring(@theStr, len(@theStr) - 4 + 1, 4)
+ substring(@thestr, charindex('-',@Thestr)+1,1)
+ right('00' + substring(@thestr, 1, charindex('-',@Thestr)-1),2)
will yield this output
2018
09
4
2018409
Since you know what the algorithm for date hashing is you can restore the original dates into a new column and then sort on it. Something like:
SELECT *, CONVERT(datetime2(1),
RIGHT(@mthweekyr, 4) + '-' +
LEFT(@mthweekyr, CHARINDEX('-', @mthweekyr) - 1) + '-' +
SUBSTRING(@mthweekyr, CHARINDEX('-', @mthweekyr) + 1,
CHARINDEX('-', @mthweekyr, CHARINDEX('-', @mthweekyr) + 1)
- CHARINDEX('-', @mthweekyr) - 1)) AS EstimatedDate
FROM theTable
ORDER BY EstimatedDate
So the above is the long, harder way.
A smarter approach would be to leave the heavy lifting to the SQL Engine and use the third parameter of the CONVERT
function , which specifies the style of the input. As the mthweekyr
basically represents a USA style of mm-d-yyyy
, the query will look like:
SELECT *, CONVERT(datetime2(1), mthweekyr, 110) AS EstimatedDate
FROM theTable
ORDER BY EstimateDate
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.