August 11, 2015 at 10:57 am
I wonder if someone can help before my head explodes
Ive got the following data in a table
sourcedata
/@836d254c/v1/HOME/INDEX
/@836d254c/v1/ASSIST/SPECIAL
/@836d254c/v1/ASSIST/SPECIAL
/@836d256c/v1/api/ASSIST/Regular/Getdata
I need to split it between two separate columns in the following format
Column1
/@836d254c
/@836d254c
/@836d254c
/@836d256c
Column2
/v1/HOME/INDEX
/v1/ASSIST/SPECIAL
/v1/ASSIST/SPECIAL
/v1/api/ASSIST/Regular/Getdata
I've tried using something like
update simons_table
set column1 = sourcedata
update [simons_table]
set [column2] = REVERSE( substring(REVERSE([column1]),1,charindex('/',reverse([column1]))))
where sourcedata like '/@%'
update [simons_table]
set [column1] = replace (column1,REVERSE( substring(REVERSE([column1]),1,charindex('/',reverse([column1])))),'')
where sourcedata like '/@%'
update [simons_table]
set [column2] = REVERSE( substring(REVERSE([column1]),1,charindex('/',reverse([column1]))))+column2
where sourcedata like '/@%'
update [simons_table]
set [column1] = replace (column1,REVERSE( substring(REVERSE([column1]),1,charindex('/',reverse([column1])))),'')
where sourcedata like '/@%'
But as each row of data in the sourcedata column can have varying amounts of '/' I'm stuck as to how to get it to work and my head might explode at this rate
August 11, 2015 at 11:25 am
Quick suggestion
😎
USE tempdb;
GO
SET NOCOUNT ON;
DECLARE @sourcedata TABLE(STR_DATA VARCHAR(100) NOT NULL);
INSERT INTO @sourcedata(STR_DATA)
VALUES
('/@836d254c/v1/HOME/INDEX' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d256c/v1/api/ASSIST/Regular/Getdata');
SELECT
SD.STR_DATA AS ORIGINAL
,LEFT(SD.STR_DATA,CHARINDEX('/v1/',SD.STR_DATA)-1) AS COLUMN_1
,REPLACE(SD.STR_DATA,LEFT(SD.STR_DATA,CHARINDEX('/v1/',SD.STR_DATA)-1),'') AS COLUMN_2
FROM @sourcedata SD;
Results
ORIGINAL COLUMN_1 COLUMN_2
------------------------------------------ ----------- -------------------------------
/@836d254c/v1/HOME/INDEX /@836d254c /v1/HOME/INDEX
/@836d254c/v1/ASSIST/SPECIAL /@836d254c /v1/ASSIST/SPECIAL
/@836d254c/v1/ASSIST/SPECIAL /@836d254c /v1/ASSIST/SPECIAL
/@836d256c/v1/api/ASSIST/Regular/Getdata /@836d256c /v1/api/ASSIST/Regular/Getdata
August 11, 2015 at 11:28 am
In order to have ANY chance at splitting this string, you HAVE to have something that is consistently true across ALL rows. Some possibilities include:
1.) The 2nd slash always starts the 2nd field.
2.) The slash immediately preceding v1 starts the 2nd field. --EDIT: Eirikur's code is an example of this, and differs only by assuming the need for an additional / after the v1
3.) The first x number of characters represents the first field.
There might be other possibilities that you will know, but I won't, but the idea is that there simply HAS to be something that is consistently true across every single row, or you are going to have a problem. If you can describe such a condition, it can probably be coded. Let us know...
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
August 11, 2015 at 12:11 pm
As an added note, REVERSE should generally only be used when it is easier to define your criteria reading from the right than it is reading from the left. So, if you were looking for the last "/". Your examples look like you are actually looking for the first "/", which means that you want to be reading from the left, so you don't want to use REVERSE.
Drew
J. Drew Allen
Business Intelligence Analyst
Philadelphia, PA
August 11, 2015 at 12:25 pm
A slightly different version of Eirikur's code. This is just to give you more ideas on the different possibilities to solve your problem.
DECLARE @sourcedata TABLE(STR_DATA VARCHAR(100) NOT NULL);
INSERT INTO @sourcedata(STR_DATA)
VALUES
('/@836d254c/v1/HOME/INDEX' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d256c/v1/api/ASSIST/Regular/Getdata');
SELECT
SD.STR_DATA AS ORIGINAL
,LEFT(SD.STR_DATA,CHARINDEX('/',SD.STR_DATA, 2)-1) AS COLUMN_1
,SUBSTRING(SD.STR_DATA,CHARINDEX('/',SD.STR_DATA, 2), 8000) AS COLUMN_2
FROM @sourcedata SD;
August 11, 2015 at 6:40 pm
Luis Cazares (8/11/2015)
A slightly different version of Eirikur's code. This is just to give you more ideas on the different possibilities to solve your problem.
DECLARE @sourcedata TABLE(STR_DATA VARCHAR(100) NOT NULL);
INSERT INTO @sourcedata(STR_DATA)
VALUES
('/@836d254c/v1/HOME/INDEX' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d256c/v1/api/ASSIST/Regular/Getdata');
SELECT
SD.STR_DATA AS ORIGINAL
,LEFT(SD.STR_DATA,CHARINDEX('/',SD.STR_DATA, 2)-1) AS COLUMN_1
,SUBSTRING(SD.STR_DATA,CHARINDEX('/',SD.STR_DATA, 2), 8000) AS COLUMN_2
FROM @sourcedata SD;
Nice!
--Jeff Moden
Change is inevitable... Change for the better is not.
August 12, 2015 at 1:38 am
For giggles here is yet another slightly modified version. The difference doesn't look much but it is an improvement over the first one of roughly 20% and 5-10% over Luis's version.
😎
USE tempdb;
GO
SET NOCOUNT ON;
DECLARE @sourcedata TABLE(STR_DATA VARCHAR(100) NOT NULL);
INSERT INTO @sourcedata(STR_DATA)
VALUES
('/@836d254c/v1/HOME/INDEX' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d256c/v1/api/ASSIST/Regular/Getdata');
;WITH BASE_DATA AS
(
SELECT
SD.STR_DATA AS ORIGINAL
,CHARINDEX('/',SD.STR_DATA,2) AS POS
FROM @sourcedata SD
)
SELECT
BD.ORIGINAL
,LEFT(BD.ORIGINAL,BD.POS - 1)
,SUBSTRING(BD.ORIGINAL,BD.POS,8000)
FROM BASE_DATA BD;
August 12, 2015 at 3:08 am
many thanks for all the help , appreciate that 🙂
August 12, 2015 at 7:39 am
Eirikur Eiriksson (8/12/2015)
For giggles here is yet another slightly modified version. The difference doesn't look much but it is an improvement over the first one of roughly 20% and 5-10% over Luis's version.😎
USE tempdb;
GO
SET NOCOUNT ON;
DECLARE @sourcedata TABLE(STR_DATA VARCHAR(100) NOT NULL);
INSERT INTO @sourcedata(STR_DATA)
VALUES
('/@836d254c/v1/HOME/INDEX' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d256c/v1/api/ASSIST/Regular/Getdata');
;WITH BASE_DATA AS
(
SELECT
SD.STR_DATA AS ORIGINAL
,CHARINDEX('/',SD.STR_DATA,2) AS POS
FROM @sourcedata SD
)
SELECT
BD.ORIGINAL
,LEFT(BD.ORIGINAL,BD.POS - 1)
,SUBSTRING(BD.ORIGINAL,BD.POS,8000)
FROM BASE_DATA BD;
Eirikur,
Since you're doing a performance test, how does this compare?
DECLARE @sourcedata TABLE(STR_DATA VARCHAR(100) NOT NULL);
INSERT INTO @sourcedata(STR_DATA)
VALUES
('/@836d254c/v1/HOME/INDEX' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d254c/v1/ASSIST/SPECIAL' )
,('/@836d256c/v1/api/ASSIST/Regular/Getdata');
SELECT
SD.STR_DATA AS ORIGINAL
,LEFT(SD.STR_DATA,ca.pos-1) AS COLUMN_1
,SUBSTRING(SD.STR_DATA,ca.pos, 8000) AS COLUMN_2
FROM @sourcedata SD
CROSS APPLY (SELECT CHARINDEX('/', SD.STR_DATA, 2) ) ca(pos)
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
August 12, 2015 at 8:06 am
WayneS (8/12/2015)
Eirikur,Since you're doing a performance test, how does this compare?
Close to identical to the CTE version in performance and funny enough the QUERYTRACEON 8607 output tree differs only in a single word (XVAR ownership), hence the server rewrites the cross apply as a CTE.
😎
August 12, 2015 at 8:19 am
Sweet. Thanks for doing that.
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
Viewing 11 posts - 1 through 10 (of 10 total)
You must be logged in to reply to this topic. Login to reply