reverse the characters of a string without changing the position of the numeric value in T-SQL
With T-SQL, I'm trying to find the easiest way to reverse the characters of a string without changing the position of the numeric value.
So for string:
abc223de11
have
edc223ba11
sql-server t-sql string
New contributor
add a comment |
With T-SQL, I'm trying to find the easiest way to reverse the characters of a string without changing the position of the numeric value.
So for string:
abc223de11
have
edc223ba11
sql-server t-sql string
New contributor
2
Reversing strings is surprisingly tricky if there are Unicode characters. T-SQL is poorly suited for such a task. Would it be possible to use, say, .Net instead? Either on application level or via CLR?
– vonPryz
14 hours ago
1
And to ask a silly question, why? Also, what version of SQL Server?
– Aaron Bertrand♦
14 hours ago
I'm using SSMS17, It's just for my personal training I just came up with this scenario to test out my t-sql skills to see if it's possible to solve it with t-sql. Because in other languages we could possibly swap characters within string easily and quickly but I couldn't do it with t-sql.
– anna
13 hours ago
add a comment |
With T-SQL, I'm trying to find the easiest way to reverse the characters of a string without changing the position of the numeric value.
So for string:
abc223de11
have
edc223ba11
sql-server t-sql string
New contributor
With T-SQL, I'm trying to find the easiest way to reverse the characters of a string without changing the position of the numeric value.
So for string:
abc223de11
have
edc223ba11
sql-server t-sql string
sql-server t-sql string
New contributor
New contributor
edited 3 hours ago
Solomon Rutzky
48.8k581177
48.8k581177
New contributor
asked 15 hours ago
annaanna
212
212
New contributor
New contributor
2
Reversing strings is surprisingly tricky if there are Unicode characters. T-SQL is poorly suited for such a task. Would it be possible to use, say, .Net instead? Either on application level or via CLR?
– vonPryz
14 hours ago
1
And to ask a silly question, why? Also, what version of SQL Server?
– Aaron Bertrand♦
14 hours ago
I'm using SSMS17, It's just for my personal training I just came up with this scenario to test out my t-sql skills to see if it's possible to solve it with t-sql. Because in other languages we could possibly swap characters within string easily and quickly but I couldn't do it with t-sql.
– anna
13 hours ago
add a comment |
2
Reversing strings is surprisingly tricky if there are Unicode characters. T-SQL is poorly suited for such a task. Would it be possible to use, say, .Net instead? Either on application level or via CLR?
– vonPryz
14 hours ago
1
And to ask a silly question, why? Also, what version of SQL Server?
– Aaron Bertrand♦
14 hours ago
I'm using SSMS17, It's just for my personal training I just came up with this scenario to test out my t-sql skills to see if it's possible to solve it with t-sql. Because in other languages we could possibly swap characters within string easily and quickly but I couldn't do it with t-sql.
– anna
13 hours ago
2
2
Reversing strings is surprisingly tricky if there are Unicode characters. T-SQL is poorly suited for such a task. Would it be possible to use, say, .Net instead? Either on application level or via CLR?
– vonPryz
14 hours ago
Reversing strings is surprisingly tricky if there are Unicode characters. T-SQL is poorly suited for such a task. Would it be possible to use, say, .Net instead? Either on application level or via CLR?
– vonPryz
14 hours ago
1
1
And to ask a silly question, why? Also, what version of SQL Server?
– Aaron Bertrand♦
14 hours ago
And to ask a silly question, why? Also, what version of SQL Server?
– Aaron Bertrand♦
14 hours ago
I'm using SSMS17, It's just for my personal training I just came up with this scenario to test out my t-sql skills to see if it's possible to solve it with t-sql. Because in other languages we could possibly swap characters within string easily and quickly but I couldn't do it with t-sql.
– anna
13 hours ago
I'm using SSMS17, It's just for my personal training I just came up with this scenario to test out my t-sql skills to see if it's possible to solve it with t-sql. Because in other languages we could possibly swap characters within string easily and quickly but I couldn't do it with t-sql.
– anna
13 hours ago
add a comment |
1 Answer
1
active
oldest
votes
I am not proud of this, but you can do it in T-SQL. This inline table-valued function breaks the string into a set of characters, and applies row numbers to just the string values, so that you can flip the set upside down.
CREATE FUNCTION dbo.SortString
(
@s varchar(64)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
( -- get a sequence number for every character in @s
WITH n AS
(
SELECT n = 1 UNION ALL SELECT n + 1 FROM n WHERE n < LEN(@s)
),
s AS
( -- break out each character, apply sequence number, test numeric
SELECT n, s = SUBSTRING(@s, n, 1), isn = ISNUMERIC(SUBSTRING(@s, n, 1))
FROM n
),
s2 AS
( -- apply reverse match pointers, but only for strings
SELECT n,s,
rn1 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n ASC) END,
rn2 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n DESC) END
FROM s
)
SELECT s2.n, New = COALESCE(s3.s, s2.s), Original = s2.s
FROM s2 LEFT OUTER JOIN s2 AS s3
ON s2.rn2 = s3.rn1
);
GO
The following call:
DECLARE @str varchar(64) = 'abc223de11';
SELECT Original, New FROM dbo.SortString(@str) ORDER BY n;
Yields the following results:
Original New
-------- ---
a e
b d
c c
2 2
2 2
3 3
d b
e a
1 1
1 1
In SQL Server 2017, you can pack the string back together with predictable order using STRING_AGG()
:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = STRING_AGG(New,'') WITHIN GROUP (ORDER BY n)
FROM dbo.SortString(@str);
In older versions, you'll need to use a FOR XML
hack:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = (SELECT '' + New
FROM dbo.SortString(@str)
ORDER BY n
FOR XML PATH, TYPE).value(N'.[1]','varchar(64)');
Results in both cases:
OriginalString QuasiReversed
-------------- -------------
abc223de11 edc223ba11
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
anna is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f230976%2freverse-the-characters-of-a-string-without-changing-the-position-of-the-numeric%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I am not proud of this, but you can do it in T-SQL. This inline table-valued function breaks the string into a set of characters, and applies row numbers to just the string values, so that you can flip the set upside down.
CREATE FUNCTION dbo.SortString
(
@s varchar(64)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
( -- get a sequence number for every character in @s
WITH n AS
(
SELECT n = 1 UNION ALL SELECT n + 1 FROM n WHERE n < LEN(@s)
),
s AS
( -- break out each character, apply sequence number, test numeric
SELECT n, s = SUBSTRING(@s, n, 1), isn = ISNUMERIC(SUBSTRING(@s, n, 1))
FROM n
),
s2 AS
( -- apply reverse match pointers, but only for strings
SELECT n,s,
rn1 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n ASC) END,
rn2 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n DESC) END
FROM s
)
SELECT s2.n, New = COALESCE(s3.s, s2.s), Original = s2.s
FROM s2 LEFT OUTER JOIN s2 AS s3
ON s2.rn2 = s3.rn1
);
GO
The following call:
DECLARE @str varchar(64) = 'abc223de11';
SELECT Original, New FROM dbo.SortString(@str) ORDER BY n;
Yields the following results:
Original New
-------- ---
a e
b d
c c
2 2
2 2
3 3
d b
e a
1 1
1 1
In SQL Server 2017, you can pack the string back together with predictable order using STRING_AGG()
:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = STRING_AGG(New,'') WITHIN GROUP (ORDER BY n)
FROM dbo.SortString(@str);
In older versions, you'll need to use a FOR XML
hack:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = (SELECT '' + New
FROM dbo.SortString(@str)
ORDER BY n
FOR XML PATH, TYPE).value(N'.[1]','varchar(64)');
Results in both cases:
OriginalString QuasiReversed
-------------- -------------
abc223de11 edc223ba11
add a comment |
I am not proud of this, but you can do it in T-SQL. This inline table-valued function breaks the string into a set of characters, and applies row numbers to just the string values, so that you can flip the set upside down.
CREATE FUNCTION dbo.SortString
(
@s varchar(64)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
( -- get a sequence number for every character in @s
WITH n AS
(
SELECT n = 1 UNION ALL SELECT n + 1 FROM n WHERE n < LEN(@s)
),
s AS
( -- break out each character, apply sequence number, test numeric
SELECT n, s = SUBSTRING(@s, n, 1), isn = ISNUMERIC(SUBSTRING(@s, n, 1))
FROM n
),
s2 AS
( -- apply reverse match pointers, but only for strings
SELECT n,s,
rn1 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n ASC) END,
rn2 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n DESC) END
FROM s
)
SELECT s2.n, New = COALESCE(s3.s, s2.s), Original = s2.s
FROM s2 LEFT OUTER JOIN s2 AS s3
ON s2.rn2 = s3.rn1
);
GO
The following call:
DECLARE @str varchar(64) = 'abc223de11';
SELECT Original, New FROM dbo.SortString(@str) ORDER BY n;
Yields the following results:
Original New
-------- ---
a e
b d
c c
2 2
2 2
3 3
d b
e a
1 1
1 1
In SQL Server 2017, you can pack the string back together with predictable order using STRING_AGG()
:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = STRING_AGG(New,'') WITHIN GROUP (ORDER BY n)
FROM dbo.SortString(@str);
In older versions, you'll need to use a FOR XML
hack:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = (SELECT '' + New
FROM dbo.SortString(@str)
ORDER BY n
FOR XML PATH, TYPE).value(N'.[1]','varchar(64)');
Results in both cases:
OriginalString QuasiReversed
-------------- -------------
abc223de11 edc223ba11
add a comment |
I am not proud of this, but you can do it in T-SQL. This inline table-valued function breaks the string into a set of characters, and applies row numbers to just the string values, so that you can flip the set upside down.
CREATE FUNCTION dbo.SortString
(
@s varchar(64)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
( -- get a sequence number for every character in @s
WITH n AS
(
SELECT n = 1 UNION ALL SELECT n + 1 FROM n WHERE n < LEN(@s)
),
s AS
( -- break out each character, apply sequence number, test numeric
SELECT n, s = SUBSTRING(@s, n, 1), isn = ISNUMERIC(SUBSTRING(@s, n, 1))
FROM n
),
s2 AS
( -- apply reverse match pointers, but only for strings
SELECT n,s,
rn1 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n ASC) END,
rn2 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n DESC) END
FROM s
)
SELECT s2.n, New = COALESCE(s3.s, s2.s), Original = s2.s
FROM s2 LEFT OUTER JOIN s2 AS s3
ON s2.rn2 = s3.rn1
);
GO
The following call:
DECLARE @str varchar(64) = 'abc223de11';
SELECT Original, New FROM dbo.SortString(@str) ORDER BY n;
Yields the following results:
Original New
-------- ---
a e
b d
c c
2 2
2 2
3 3
d b
e a
1 1
1 1
In SQL Server 2017, you can pack the string back together with predictable order using STRING_AGG()
:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = STRING_AGG(New,'') WITHIN GROUP (ORDER BY n)
FROM dbo.SortString(@str);
In older versions, you'll need to use a FOR XML
hack:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = (SELECT '' + New
FROM dbo.SortString(@str)
ORDER BY n
FOR XML PATH, TYPE).value(N'.[1]','varchar(64)');
Results in both cases:
OriginalString QuasiReversed
-------------- -------------
abc223de11 edc223ba11
I am not proud of this, but you can do it in T-SQL. This inline table-valued function breaks the string into a set of characters, and applies row numbers to just the string values, so that you can flip the set upside down.
CREATE FUNCTION dbo.SortString
(
@s varchar(64)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
( -- get a sequence number for every character in @s
WITH n AS
(
SELECT n = 1 UNION ALL SELECT n + 1 FROM n WHERE n < LEN(@s)
),
s AS
( -- break out each character, apply sequence number, test numeric
SELECT n, s = SUBSTRING(@s, n, 1), isn = ISNUMERIC(SUBSTRING(@s, n, 1))
FROM n
),
s2 AS
( -- apply reverse match pointers, but only for strings
SELECT n,s,
rn1 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n ASC) END,
rn2 = CASE WHEN isn = 0 THEN ROW_NUMBER() OVER
(PARTITION BY isn ORDER BY n DESC) END
FROM s
)
SELECT s2.n, New = COALESCE(s3.s, s2.s), Original = s2.s
FROM s2 LEFT OUTER JOIN s2 AS s3
ON s2.rn2 = s3.rn1
);
GO
The following call:
DECLARE @str varchar(64) = 'abc223de11';
SELECT Original, New FROM dbo.SortString(@str) ORDER BY n;
Yields the following results:
Original New
-------- ---
a e
b d
c c
2 2
2 2
3 3
d b
e a
1 1
1 1
In SQL Server 2017, you can pack the string back together with predictable order using STRING_AGG()
:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = STRING_AGG(New,'') WITHIN GROUP (ORDER BY n)
FROM dbo.SortString(@str);
In older versions, you'll need to use a FOR XML
hack:
DECLARE @str varchar(64) = 'abc223de11';
SELECT
OriginalString = @str,
QuasiReversed = (SELECT '' + New
FROM dbo.SortString(@str)
ORDER BY n
FOR XML PATH, TYPE).value(N'.[1]','varchar(64)');
Results in both cases:
OriginalString QuasiReversed
-------------- -------------
abc223de11 edc223ba11
answered 13 hours ago
Aaron Bertrand♦Aaron Bertrand
152k18289489
152k18289489
add a comment |
add a comment |
anna is a new contributor. Be nice, and check out our Code of Conduct.
anna is a new contributor. Be nice, and check out our Code of Conduct.
anna is a new contributor. Be nice, and check out our Code of Conduct.
anna is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f230976%2freverse-the-characters-of-a-string-without-changing-the-position-of-the-numeric%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Reversing strings is surprisingly tricky if there are Unicode characters. T-SQL is poorly suited for such a task. Would it be possible to use, say, .Net instead? Either on application level or via CLR?
– vonPryz
14 hours ago
1
And to ask a silly question, why? Also, what version of SQL Server?
– Aaron Bertrand♦
14 hours ago
I'm using SSMS17, It's just for my personal training I just came up with this scenario to test out my t-sql skills to see if it's possible to solve it with t-sql. Because in other languages we could possibly swap characters within string easily and quickly but I couldn't do it with t-sql.
– anna
13 hours ago