Truncate specific number of characters in SQL cells - sql

I have Description column in a table
Description
---------------
AA Check
B1 Check
RD/AA Check
WD_FA Examine
FF Examine
AA Pass
B2 Check
Examine
The desired output
Description
---------------
Check
Examine
Pass
Basically a case statement where it truncates from the left side of the cell. NOTE that the list goes on with different names and conditions, and some cells do not need modification (like the last row), so something similar to a case statement but not returning NULL if I did not specify the condition
Thank you

This removes the data up to the 1st space
case when x like '% %'
then substring(x, charindex(' ', x) +1, 8000)
else x
end
'AA Examine Device' -> 'Examine Device'
And this extracts the last word:
case when x like '% %'
then right(x, charindex(' ', reverse(x)) -1)
else x
end
'AA Examine Device' -> 'Device'

Following the white space that you have, and using DISTINCT, this gets the last word following a white space or returns the word if it's the only word.
declare #Description table (Description varchar(64))
insert into #Description
values
('AA Check'),
('B1 Check'),
('RD/AA Check'),
('WD_FA Examine'),
('FF Examine'),
('AA Pass'),
('B2 Check'),
('Examine')
select distinct
right([Description],len([Description]) - charindex(' ',[Description]))
from #Description

You can do it like below :
select distinct substring(Description, charindex(' ', Description) + 1, len(Description))

The question is too broad, but you can use something like that
DECLARE #Product TABLE (
[Description] nvarchar(255),
Condition int
);
INSERT #Product ([Description], Condition)
select 'AA Check', 1 union all
select 'B1 Check', 2 union all
select 'RD/AA Check', 3 union all
select 'WD_FA Examine', 3 union all
select 'FF Examine', 4 union all
select 'AA Pass', 1 union all
select 'B2 Check', 5 union all
select 'Examine', 6
select
[Description],
case
when Condition = 1 then replace([Description],'AA ','')
when Condition = 2 then replace([Description],'B1 ','')
when Condition = 3 then ltrim(rtrim(right([Description],len([Description]) - 5)))
when Condition = 5 then replace([Description],'B2 ','')
when Condition = 6 then [Description]
else
''
end as 'NewDescription'
from #Product
I hope it helps 🙂

Perhaps something like this:
;WITH CTE (Column1) AS (
SELECT * FROM (
VALUES
(' AA Check '), (' B1 Check'), (' RD/AA Check '), (' WD_FA Examine '), (' FF Examine '),
(' AA Pass '), (' B2 Check '), (' Examine ')
) AS A (Column1)
)
SELECT
CASE WHEN CHARINDEX('Check', Column1) > 0 THEN SUBSTRING(Column1, CHARINDEX('Check', Column1), 5)
WHEN CHARINDEX('Examine', Column1) > 0 THEN SUBSTRING(Column1, CHARINDEX('Examine', Column1), 7)
WHEN CHARINDEX('Pass', Column1) > 0 THEN SUBSTRING(Column1, CHARINDEX('Pass', Column1), 4)
END AS Results
FROM CTE
It would be painful if you have a lot of variables though.

CREATE TABLE [A] ( [Description] VARCHAR(100));
INSERT [A]
VALUES
---------------
( 'AA Check' )
,( 'B1 Check' )
,( 'RD/AA Check' )
,( 'WD_FA Examine' )
,( 'FF Examine' )
,( 'AA Pass' )
,( 'B2 Check' )
,( 'Examine' )
,( 'Examine Device' );
SELECT DISTINCT
CASE
WHEN [Description] COLLATE Latin1_General_BIN LIKE '[A-Z][a-z]%' THEN
[Description]
WHEN [Description] COLLATE Latin1_General_BIN LIKE '[A-Z][A-Z0-9]%' THEN
SUBSTRING([Description], CHARINDEX(' ', [Description]) + 1, 8000)
END AS [Description]
FROM
[A];
DROP TABLE [A];

Related

parsing first and last names from sql table

I have a column in my SQL Server 2008 database that contains c/o Full Name. I'm having issues getting the First and Last names separated. I have the c/o in its own column, but I need the First/Last Names. I know that there is an issue with the second and third case statement, but I'm not sure what I need to change. Should I be storing index variables somewhere to reference them?
Declare #t table ( [name] varchar(100) )
INSERT INTO #t ( Name )
SELECT Street1 FROM tblPeople
WHERE CO = 'Y' AND LastName NOT LIKE 'SUMMERHAVEN INC' AND Street1 Like '%c/o%'
SELECT
[name],
CHARINDEX(' ', [name]),
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
LEFT([name],CHARINDEX(' ',[name])-1)
ELSE
[name]
END as CO,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name])+1, ( LEN([name]) - CHARINDEX(' ',[name])+1) )
ELSE
NULL
END as FIRST_NAME,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name])+1, ( LEN([name]) - CHARINDEX(' ',[name])+1) )
ELSE
NULL
END as LAST_NAME
FROM #t
To my surprise, PARSENAME() was available in 2008
Consider the following
Declare #YourTable table (Name varchar(50))
Insert Into #YourTable values
('c/o Cher')
,('c/o John Smith')
,('John Smith')
Select *
,FirstName=parsename(replace(ltrim(rtrim(replace(name,'c/o',''))),' ','.'),2)
,LastName =parsename(replace(ltrim(rtrim(replace(name,'c/o',''))),' ','.'),1)
From #YourTable
Returns
Name FirstName LastName
c/o Cher NULL Cher
c/o John Smith John Smith
John Smith John Smith
Disclosure: this is a bad idea to parse the data like this, but here you go:
Declare #t table ( [name] varchar(100) )
insert into #t ( Name ) values ('c/o Full Name')
SELECT
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
LEFT([name],CHARINDEX(' ',[name])-1)
ELSE
[name]
END as CO,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name])+1, CHARINDEX(' ',[name]) )
ELSE
NULL
END as FIRST_NAME,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name], CHARINDEX(' ',[name])+1), len([name]))
ELSE
NULL
END as LAST_NAME
FROM #t
Here's an approach using Common Table Expressions which so that the logic for finding the spaces to break on is reasonably self-documenting.
Declare #t table ( [name] varchar(100) )
insert into #t ( Name )
select 'one two three'
union select 'a bc def'
union select 'one two'
union select 'one'
;with cte1 as
(
select name
,charindex(' ', name) FirstSpace
from #t
)
, cte2 as (
select name
, FirstSpace
,charindex(' ', name, FirstSpace+1) SecondSpace
from cte1
)
select name
, FirstSpace
, SecondSpace
, case when FirstSpace=0 then name else substring(name, 1, FirstSpace-1) end Company
, case when SecondSpace=0 then null else substring(name, FirstSpace+1, SecondSpace-FirstSpace-1) end FirstName
, case when SecondSpace=0 or SecondSpace=len(name) then null else substring(name, SecondSpace+1, len(name)-SecondSpace) end LastName
from cte2

Split semicolon-delimited column into multiple columns

I'm trying to split a column, in SQL, into multiple columns.
My data looks like this:
Column1 | Column2 | Column3
ABC | 123 | User7;User9
nbm | qre | User1;User2;User3
POI | kjh | User1;User4;User5;User9
I need to split the Column3 into 4 new columns - each column containing the first "User". Each value within this column is separated by a semi-colon. One of the problems I have is that Column3 can have any number of users listed (all separated by semi-colons), so I don't know how many "new" columns I would need added.
The final output would need to look like:
Column1 | Column2 | Column3 | NewColumn1 | NewColumn2 | ETC.
Besides the fact that this is bad design here is a solution:
Just paste this into an empty query window and execute. Adapt to your needs...
declare #tbl TABLE(Column1 VARCHAR(15),Column2 VARCHAR(15),Column3 VARCHAR(150));
INSERT INTO #tbl VALUES
('ABC','123','User7;User9')
,('nbm','qre','User1;User2;User3')
,('POI','kjh','User1;User4;User5;User9');
WITH Splitted AS
(
SELECT Column1,Column2,CAST('<x>'+REPLACE(Column3,';','</x><x>')+'</x>' AS XML) AS Col3Splitted
FROM #tbl
)
SELECT Column1,Column2,Col3Splitted
,Col3Splitted.value('x[1]','varchar(max)') AS Column4
,Col3Splitted.value('x[2]','varchar(max)') AS Column5
,Col3Splitted.value('x[3]','varchar(max)') AS Column6
,Col3Splitted.value('x[4]','varchar(max)') AS Column7
/*Add as many as you need*/
FROM Splitted
Following the discussion with #SeanLang I add this dynamic approach. It will count the highest number of semicolons in Column3 and build the statement above dynamically.
CREATE TABLE #tbl (Column1 VARCHAR(15),Column2 VARCHAR(15),Column3 VARCHAR(150));
INSERT INTO #tbl VALUES
('ABC','123','User7;User9')
,('nbm','qre','User1;User2;User3')
,('POI','kjh','User1;User4;User5;User9');
DECLARE #sql VARCHAR(MAX)=
'WITH Splitted AS
(
SELECT Column1,Column2,CAST(''<x>''+REPLACE(Column3,'';'',''</x><x>'')+''</x>'' AS XML) AS Col3Splitted
FROM #tbl
)
SELECT Column1,Column2';
DECLARE #counter INT = 0;
WHILE #counter<=(SELECT MAX(LEN(Column3) - LEN(REPLACE(Column3, ';', ''))) from #tbl)
BEGIN
SET #counter=#counter+1;
SET #sql=#sql+',Col3Splitted.value(''x[' + CAST(#counter AS VARCHAR(10)) + ']'',''varchar(max)'') AS Column' + CAST(#counter+3 AS VARCHAR(10));
END
SET #sql=#sql+ ' FROM Splitted;';
EXEC (#sql);
DROP TABLE #tbl;
Here is a method that will be 100% dynamic. It will produce any number of columns based solely on the data it finds. The prevailing method for this around SO is a dynamic pivot. I prefer a dynamic crosstab as I find the syntax less obtuse and it has a slight benefit from a performance standpoint too. :)
Here is an article which explains this methodology very well. http://www.sqlservercentral.com/articles/Crosstab/65048/
Also, I am using the DelimitedSplit8K function originally penned by Jeff Moden and improved over time through the community. You can read about it and find the code for it here. http://www.sqlservercentral.com/articles/Tally+Table/72993/
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something;
create table #something
(
Column1 varchar(5)
, Column2 varchar(5)
, Column3 varchar(50)
);
insert #something
select 'ABC', '123', 'User7;User9' union all
select 'nbm', 'qre', 'User1;User2;User3' union all
select 'POI', 'kjh', 'User1;User4;User5;User9';
declare #StaticPortion nvarchar(2000) = 'with orderedResults as
(
select s.Column1
, s.Column2
, x.Item
, x.ItemNumber
from #something s
cross apply dbo.DelimitedSplit8K(Column3, '';'') x
)
select Column1
, Column2
';
declare #DynamicPortion nvarchar(max) = '';
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select #DynamicPortion = #DynamicPortion + ', MAX(Case when ItemNumber = ' + CAST(N as varchar(6)) + ' then Item end) as Subject' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 COUNT(*)
from #something s
cross apply dbo.DelimitedSplit8K(Column3, ';') x
group by Column1
Order by COUNT(*) desc
);
declare #FinalStaticPortion nvarchar(2000) = ' from orderedResults group by Column1, Column2 order by Column1, Column2';
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
select #SqlToExecute;
--uncomment the following line when you are sure this is what you want to execute.
--exec sp_executesql #SqlToExecute;
For MySQl below code can be used. This is just a sample code
#num_Column3 := 1 + LENGTH(#Column3) - LENGTH(REPLACE(#Column3, '|', '')) AS num_Column3
,IF(#num_Column3 > 0, SUBSTRING_INDEX(SUBSTRING_INDEX(#Column3)), '|', 1), '|', -1), '') AS RC_user

T-SQL split string based on delimiter

I have some data that I would like to split based on a delimiter that may or may not exist.
Example data:
John/Smith
Jane/Doe
Steve
Bob/Johnson
I am using the following code to split this data into First and Last names:
SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
The results I would like:
FirstName---LastName
John--------Smith
Jane--------Doe
Steve-------NULL
Bob---------Johnson
This code works just fine as long as all the rows have the anticipated delimiter, but errors out when a row does not:
"Invalid length parameter passed to the LEFT or SUBSTRING function."
How can I re-write this to work properly?
May be this will help you.
SELECT SUBSTRING(myColumn, 1, CASE CHARINDEX('/', myColumn)
WHEN 0
THEN LEN(myColumn)
ELSE CHARINDEX('/', myColumn) - 1
END) AS FirstName
,SUBSTRING(myColumn, CASE CHARINDEX('/', myColumn)
WHEN 0
THEN LEN(myColumn) + 1
ELSE CHARINDEX('/', myColumn) + 1
END, 1000) AS LastName
FROM MyTable
For those looking for answers for SQL Server 2016+. Use the built-in STRING_SPLIT function
Eg:
DECLARE #tags NVARCHAR(400) = 'clothing,road,,touring,bike'
SELECT value
FROM STRING_SPLIT(#tags, ',')
WHERE RTRIM(value) <> '';
Reference: https://msdn.microsoft.com/en-nz/library/mt684588.aspx
Try filtering out the rows that contain strings with the delimiter and work on those only like:
SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
WHERE CHARINDEX('/', myColumn) > 0
Or
SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
WHERE myColumn LIKE '%/%'
SELECT CASE
WHEN CHARINDEX('/', myColumn, 0) = 0
THEN myColumn
ELSE LEFT(myColumn, CHARINDEX('/', myColumn, 0)-1)
END AS FirstName
,CASE
WHEN CHARINDEX('/', myColumn, 0) = 0
THEN ''
ELSE RIGHT(myColumn, CHARINDEX('/', REVERSE(myColumn), 0)-1)
END AS LastName
FROM MyTable
ALTER FUNCTION [dbo].[split_string](
#delimited NVARCHAR(MAX),
#delimiter NVARCHAR(100)
) RETURNS #t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
AS
BEGIN
DECLARE #xml XML
SET #xml = N'<t>' + REPLACE(#delimited,#delimiter,'</t><t>') + '</t>'
INSERT INTO #t(val)
SELECT r.value('.','varchar(MAX)') as item
FROM #xml.nodes('/t') as records(r)
RETURN
END
I just wanted to give an alternative way to split a string with multiple delimiters, in case you are using a SQL Server version under 2016.
The general idea is to split out all of the characters in the string, determine the position of the delimiters, then obtain substrings relative to the delimiters. Here is a sample:
-- Sample data
DECLARE #testTable TABLE (
TestString VARCHAR(50)
)
INSERT INTO #testTable VALUES
('Teststring,1,2,3')
,('Test')
DECLARE #delimiter VARCHAR(1) = ','
-- Generate numbers with which we can enumerate
;WITH Numbers AS (
SELECT 1 AS N
UNION ALL
SELECT N + 1
FROM Numbers
WHERE N < 255
),
-- Enumerate letters in the string and select only the delimiters
Letters AS (
SELECT n.N
, SUBSTRING(t.TestString, n.N, 1) AS Letter
, t.TestString
, ROW_NUMBER() OVER ( PARTITION BY t.TestString
ORDER BY n.N
) AS Delimiter_Number
FROM Numbers n
INNER JOIN #testTable t
ON n <= LEN(t.TestString)
WHERE SUBSTRING(t.TestString, n, 1) = #delimiter
UNION
-- Include 0th position to "delimit" the start of the string
SELECT 0
, NULL
, t.TestString
, 0
FROM #testTable t
)
-- Obtain substrings based on delimiter positions
SELECT t.TestString
, ds.Delimiter_Number + 1 AS Position
, SUBSTRING(t.TestString, ds.N + 1, ISNULL(de.N, LEN(t.TestString) + 1) - ds.N - 1) AS Delimited_Substring
FROM #testTable t
LEFT JOIN Letters ds
ON t.TestString = ds.TestString
LEFT JOIN Letters de
ON t.TestString = de.TestString
AND ds.Delimiter_Number + 1 = de.Delimiter_Number
OPTION (MAXRECURSION 0)
The examples above work fine when there is only one delimiter, but it doesn't scale well for multiple delimiters. Note that this will only work for SQL Server 2016 and above.
/*Some Sample Data*/
DECLARE #mytable TABLE ([id] VARCHAR(10), [name] VARCHAR(1000));
INSERT INTO #mytable
VALUES ('1','John/Smith'),('2','Jane/Doe'), ('3','Steve'), ('4','Bob/Johnson')
/*Split based on delimeter*/
SELECT P.id, [1] 'FirstName', [2] 'LastName', [3] 'Col3', [4] 'Col4'
FROM(
SELECT A.id, X1.VALUE, ROW_NUMBER() OVER (PARTITION BY A.id ORDER BY A.id) RN
FROM #mytable A
CROSS APPLY STRING_SPLIT(A.name, '/') X1
) A
PIVOT (MAX(A.[VALUE]) FOR A.RN IN ([1],[2],[3],[4],[5])) P
These all helped me get to this. I am still on 2012 but now have something quick that will allow me to split a string, even if string has varying numbers of delimiters, and grab the nth substring from that string. It's quick too. I know this post is old, but it took me forever to find something so hopefully this will help someone else.
CREATE FUNCTION [dbo].[SplitsByIndex]
(#separator VARCHAR(20) = ' ',
#string VARCHAR(MAX),
#position INT
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #results TABLE
(id INT IDENTITY(1, 1),
chrs VARCHAR(8000)
);
DECLARE #outResult VARCHAR(8000);
WITH X(N)
AS (SELECT 'Table1'
FROM(VALUES(0), (0), (0), (0), (0), (0), (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T(C)),
Y(N)
AS (SELECT 'Table2'
FROM X A1,
X A2,
X A3,
X A4,
X A5,
X A6,
X A7,
X A8), -- Up to 16^8 = 4 billion
T(N)
AS (SELECT TOP (ISNULL(LEN(#string), 0)) ROW_NUMBER() OVER(
ORDER BY
(
SELECT NULL
)) - 1 N
FROM Y),
Delim(Pos)
AS (SELECT t.N
FROM T
WHERE(SUBSTRING(#string, t.N, LEN(#separator + 'x') - 1) LIKE #separator
OR t.N = 0)),
Separated(value)
AS (SELECT SUBSTRING(#string, d.Pos + LEN(#separator + 'x') - 1, LEAD(d.Pos, 1, 2147483647) OVER(
ORDER BY
(
SELECT NULL
))-d.Pos - LEN(#separator))
FROM Delim d
WHERE #string IS NOT NULL)
INSERT INTO #results(chrs)
SELECT s.value
FROM Separated s
WHERE s.value <> #separator;
SELECT #outResult =
(
SELECT chrs
FROM #results
WHERE id = #position
);
RETURN #outResult;
END;
This can be used like this:
SELECT [dbo].[SplitsByIndex](' ',fieldname,2)
from tablename
I would protect the substring operation by always appending a delimiter to the test strings. This makes the parsing much simpler. Your code may now rely on finding the right pattern, and not need to cope with special cases.
SELECT SUBSTRING(myColumn + '/', 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn + '/', CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
It eliminates edge cases and conditionals and cases.
Always add an extra delimiter at the end, then the challenge case is no problem.

How to split a single column values to multiple column values?

I have a problem splitting single column values to multiple column values.
For Example:
Name
------------
abcd efgh
ijk lmn opq
asd j. asdjja
asb (asdfas) asd
asd
and I need the output something like this:
first_name last_name
----------------------------------
abcd efgh
ijk opq
asd asdjja
asb asd
asd null
The middle name can be omitted (no need for a middle name) The columns are already created and need to insert the data from that single Name column.
Your approach won't deal with lot of names correctly but...
SELECT CASE
WHEN name LIKE '% %' THEN LEFT(name, Charindex(' ', name) - 1)
ELSE name
END,
CASE
WHEN name LIKE '% %' THEN RIGHT(name, Charindex(' ', Reverse(name)) - 1)
END
FROM YourTable
An alternative to Martin's
select LEFT(name, CHARINDEX(' ', name + ' ') -1),
STUFF(name, 1, Len(Name) +1- CHARINDEX(' ',Reverse(name)), '')
from somenames
Sample table
create table somenames (Name varchar(100))
insert somenames select 'abcd efgh'
insert somenames select 'ijk lmn opq'
insert somenames select 'asd j. asdjja'
insert somenames select 'asb (asdfas) asd'
insert somenames select 'asd'
insert somenames select ''
insert somenames select null
;WITH Split_Names (Name, xmlname)
AS
(
SELECT
Name,
CONVERT(XML,'<Names><name>'
+ REPLACE(Name,' ', '</name><name>') + '</name></Names>') AS xmlname
FROM somenames
)
SELECT
xmlname.value('/Names[1]/name[1]','varchar(100)') AS first_name,
xmlname.value('/Names[1]/name[2]','varchar(100)') AS last_name
FROM Split_Names
and also check the link below for reference
http://jahaines.blogspot.in/2009/06/converting-delimited-string-of-values.html
What you need is a split user-defined function. With that, the solution looks like
With SplitValues As
(
Select T.Name, Z.Position, Z.Value
, Row_Number() Over ( Partition By T.Name Order By Z.Position ) As Num
From Table As T
Cross Apply dbo.udf_Split( T.Name, ' ' ) As Z
)
Select Name
, FirstName.Value
, Case When ThirdName Is Null Then SecondName Else ThirdName End As LastName
From SplitValues As FirstName
Left Join SplitValues As SecondName
On S2.Name = S1.Name
And S2.Num = 2
Left Join SplitValues As ThirdName
On S2.Name = S1.Name
And S2.Num = 3
Where FirstName.Num = 1
Here's a sample split function:
Create Function [dbo].[udf_Split]
(
#DelimitedList nvarchar(max)
, #Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
+ #DelimitedList
+ Case When Right(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
As List
, Len(#Delimiter) As DelimiterLen
)
, Numbers As
(
Select TOP( Coalesce(DataLength(#DelimitedList)/2,0) ) Row_Number() Over ( Order By c1.object_id ) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(#Delimiter, CL.list, N.Value + 1)
- ( CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen )
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value <= DataLength(CL.List) / 2
And Substring(CL.List, N.Value, CL.DelimiterLen) = #Delimiter
)
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(rent, ' ', 1), ' ', -1) AS currency,
SUBSTRING_INDEX(SUBSTRING_INDEX(rent, ' ', 3), ' ', -1) AS rent
FROM tolets
I used it recently:
select
substring(name,1,charindex(' ',name)-1) as Col1,
substring(name,charindex(' ',name)+1,len(name)) as Col2
from TableName
Here is how I did this on a SQLite database:
SELECT SUBSTR(name, 1,INSTR(name, " ")-1) as Firstname,
SUBSTR(name, INSTR(name," ")+1, LENGTH(name)) as Lastname
FROM YourTable;
Hope it helps.

sql query complex

I have table where in a table called test which have 4 fields.one field named as listing, I have 1,2,3,4,5,6 multiple values separated by comma, I need to check whether in that table and in that particular field an id say 4 is there or not.. by a sql query.
You database design is wrong, that's why you have problems querying the data. You should have the values in a separate table, so that teach value is in it's own field. Then it would be easy to find the records:
select t.testId
from test t
inner join listing l on l.testId = t.testId
where l.id = 4
Now you have to use some ugly string comparison to find the records:
select testId
from test
where ','+listing+',' like '%,4,%'
You can try
SELECT *
FROM YourTable
WHERE REPLACE(Col, ' ', '') LIKE '4,%' --Starts with
OR REPLACE(Col, ' ', '') LIKE '%,4' --Ends with
OR REPLACE(Col, ' ', '') LIKE '%,4,%' --Contains
OR REPLACE(Col, ' ', '') = '4' --Equals
Just as a matter of interest, have a look at this
DECLARE #delimiter NVARCHAR(5),
#Val INT
SELECT #Val = 40
SELECT #delimiter = ','
DECLARE #YourTable TABLE(
ID INT,
Vals VARCHAR(50)
)
INSERT INTO #YourTable (ID,Vals) SELECT 1, '1,2,3,4,5,6,7,8'
DECLARE #TempTable TABLE(
ID INT,
Vals XML
)
INSERT INTO #TempTable
SELECT ID,
CAST('<d>' + REPLACE(Vals, #delimiter, '</d><d>') + '</d>' AS XML)
FROM #YourTable
SELECT *
FROM #TempTable tt
WHERE EXISTS(
SELECT T.split.value('.', 'nvarchar(max)') AS data
FROM tt.Vals.nodes('/d') T(split)
WHERE T.split.value('.', 'nvarchar(max)') = #Val
)
The common approach is to parse the list into a table variable or table-valued function, then either join against the table, or use an EXISTS sub-query.
There are lots of examples on how to do this:
http://www.bing.com/search?setmkt=en-US&q=SQL+parse+list+into+table
You could use an instring function in the where clause and in the select clause:
Oracle:
select substr(column, instr(column, '1', 1), 1)
where instr(column, '1', 1) > 0
works if you want a single value. Alternatively you can use a combination of case or decode statements to create a single column for each possible value:
select
decode(instr(column, '1', 1), 0, substr(column, instr(column, '1', 1), 1), null) c1,
decode(instr(column, '2', 1), 0, substr(column, instr(column, '2', 1), 1), null) c2,
decode(instr(column, '3', 1), 0, substr(column, instr(column, '3', 1), 1), null) c3
The beauty of this approach for such a poorly normalised set of data is you can save this as a view and then run SQL on that, so if you save the above you could use:
select c1, c2 from view where c1 is not null or c2 is not null
NB. In other dbms you might have to use different syntax, possibly the case rather decode statement
If you need to find 4 and only 4 (ie not 14 or 24 or 40 etc) you should use
SELECT * FROM foo WHERE col LIKE '%, 4,%'
or
SELECT * FROM foo WHERE col LIKE '%,4,%'
if there are no spaces between the commas and numbers
How about this?
Select * From Foo Where Col like '%4%'