Select first element of a comma-separated list - sql

I have a field column that contains values like
4
12,3
8,5,6,7
I'm going to write a SELECT statement, whose result would be:
4
12
8
How can I do it?

Try this
I'm hoping you are looking for this kind of solution.
DECLARE #table TABLE
(
ID INT IDENTITY(1,1),
Value NVARCHAR(MAX)
)
INSERT INTO #table VALUES('4'),('12,3'),('8,5,6,7')
select *,
IIF(CHARINDEX(',', [Value]) = 0, [Value],SUBSTRING([Value],1,(CHARINDEX(',',[Value])-1))) AS [OutPut]
from #table
Output

Try this
For SQL Server:
select if(charindex(',', numbers) = 0, numbers, LEFT(numbers, charindex(',', numbers) - 1))
from table;
For MySQL:
select if(instr(numbers, ',') = 0, numbers, LEFT(numbers, instr(numbers, ',') - 1))
from table;

Try this for SQL server
DECLARE #CSV_Split TABLE
(
Id INT IDENTITY(1,1),
CSVData NVARCHAR(MAX)
)
INSERT INTO #CSV_Split VALUES('4'),('12,3'),('8,5,6,7')
select *,LEFT(CSVData, CHARINDEX(',', CSVData + ',') - 1)
from #CSV_Split
The output is something like this:

Related

How to split string with delimiter and get the first value

I have the following query where I have a table which is storing from information with a delimiter
SQL version - Microsoft SQL Azure (RTM) - 12.0.2000.8
DECLARE #commanTable TABLE
(
CommaId NVARCHAR(MAX),
Name NVARCHAR(500)
)
DECLARE #commanTable1 TABLE
(
CommaId INT,
Name NVARCHAR(500)
)
INSERT INTO #commanTable VALUES ('2324205.3933251.7336404', 'Test1'),
('2324206.3933252.7336405', 'Test2')
INSERT INTO #commanTable1 (CommaId, Name)
SELECT value, Name
FROM #commanTable CROSS APPLY STRING_SPLIT(CommaId,'.');
SELECT * FROM #commanTable1
Getting the following results
Where I need the results to be
If you only interested in the first value, you don't need to use STRING_SPLIT(). You can simply use charindex() to find the first delimiter and use left() to extract it
SELECT *, left(CommaId, charindex('.', CommaId) - 1)
FROM #commanTable
Edit : if you always wanted the nth value, you can do a cascade charindex(). Provided that the n is not too huge. Else use the function that I provided in the comment.
SELECT *,
item1 = left(CommaId, p1.p - 1),
item2 = substring(CommaId, p1.p + 1, p2.p - p1.p - 1)
FROM #commanTable t
cross apply
(
select p = charindex('.', CommaId)
) p1
cross apply
(
select p = charindex('.', CommaId, p1.p + 1)
) p2

Inserting multiple value in table with String input

I am passing one string to store procedure : 1:20,2:30,4:50
It contains id and appropriate value for it.
how can I add value as shown in below table in database.
ID Value
1 20
2 30
4 50
I have already "stringSplit" function which works perfectly and gives out put in row value some think like this :
1:20
2:30
4:50
can anyone please help me to insert data into table with any solution.
i already try this solution
insert <table> (colname)
select y.item
from dbo.SplitString(#testString, ':') x
cross apply
dbo.SplitString(x.item, ',') y
but this will return duplicate value as more as id value.
my store procedure is
CREATE PROCEDURE [dbo].[temp_result_insert]
#dataString varchar(max)
AS
insert into tempTable(id,marks)
select x.Item,y.Item
from dbo.SplitStringVarcahr(#dataString, ':') x
cross apply
dbo.SplitStringVarcahr(x.Item,',') y
RETURN 0
As you already splitted into rows and you want insert into some table by splliting into two columns may be this works
CREATE TABLE #Test(ID INT,Val INT)
declare #t table (val varchar(50))
insert into #t (val)values ('1:20,2:30,4:50')
declare #str varchar(max)
;with cte as (
SELECT
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT
CAST ('<M>' + REPLACE([val], ',', '</M><M>') + '</M>' AS XML) AS String
FROM #t) AS A CROSS APPLY String.nodes ('/M') AS Split(a))
INSERT INTO #Test
select SUBSTRING(String,0,CHARINDEX(':',String)),REVERSE(SUBSTRING(reverse(String),0,CHARINDEX(':',reverse(String)))) from cte
select * from #test
You can also try XML.nodes() and string functions to spit the data. Something like this
DECLARE #var VARCHAR(100) = '1:20,2:30,4:50'
DECLARE #xml xml = CONVERT(xml, '<r>' + REPLACE(#var,',','</r><r>') + '</r>')
SELECT LEFT(val,cindex - 1) c1,RIGHT(val,LEN(val) - cindex) c2
FROM
(
SELECT CHARINDEX(':',c.value('text()[1]','VARCHAR(100)')) cindex,c.value('text()[1]','VARCHAR(100)') val
FROM #xml.nodes('r') as t(c))c
Use substring and Charindex:
SELECT Substring(col, 0, Charindex(col, ':') - 1) AS id,
Substring(col, Charindex(col, ':') + 1, Len(col)-Charindex(col, ':')) AS value
FROM splittedtable

Split the query string with repeatative special characters using SQL

This is my String
Declare #qstr as varchar(max)='hireteammember.aspx?empemail=kuldeep#asselsolutions.com&empid=376&empname=kuldeep&adminname=TMA1&term=5&teamid=161&contactid=614¥1&WP=100¥5¥Months&Amt=500&DueDay=5&StrDt=12/31/2013&MemCatg=Employees&StrTm=21:05&PlnHrs=5&WrkDays=true¥true¥true¥true¥true¥false¥false'
I want to extract the values of empid,empname,adminname,term,teamid,contactid,WP,Months,Dueday,StrDt,MemCatgmStrTm,PlnHrs,WrkDays and assign them to new variables
I have used
select ( SUBSTRING(#qstr,CHARINDEX('=',#qstr)+1,CHARINDEX('&',#qstr)-CHARINDEX('=',#qstr)-1)))
but only getting the 'empemail' , for the next occurance of special char '&' , not able to get the values of further terms , if i am using '&' in spite of '=' .
Help me to split the whole string
How about using XML to split the values into rows, and then splitting them into columns.
Something like
Declare #qstr as varchar(max)='hireteammember.aspx?empemail=kuldeep#asselsolutions.com&empid=376&empname=kuldeep&adminname=TMA1&term=5&teamid=161&contactid=614¥1&WP=100¥5¥Months&Amt=500&DueDay=5&StrDt=12/31/2013&MemCatg=Employees&StrTm=21:05&PlnHrs=5&WrkDays=true¥true¥true¥true¥true¥false¥false'
DECLARe #str VARCHAR(MAX) = SUBSTRING(#qstr,CHARINDEX('?',#qstr,0) + 1, LEN(#qstr)-CHARINDEX('?',#qstr,0))
DECLARE #xml XML
SELECT #xml = CAST('<d>' + REPLACE(#str, '&', '</d><d>') + '</d>' AS XML)
;WITH Vals AS (
SELECT T.split.value('.', 'nvarchar(max)') AS data
FROM #xml.nodes('/d') T(split)
)
SELECT LEFT(data,CHARINDEX('=',data,0) - 1),
RIGHT(data,LEN(data) - CHARINDEX('=',data,0))
FROM Vals
SQL Fiddle DEMO
CREATE FUNCTION dbo.SplitQueryString (#s varchar(8000))
RETURNS table
AS
RETURN (
WITH splitter_cte AS (
SELECT CHARINDEX('&', #s) as pos, 0 as lastPos
UNION ALL
SELECT CHARINDEX('&', #s, pos + 1), pos
FROM splitter_cte
WHERE pos > 0
),
pair_cte AS (
SELECT chunk,
CHARINDEX('=', chunk) as pos
FROM (
SELECT SUBSTRING(#s, lastPos + 1,
case when pos = 0 then 80000
else pos - lastPos -1 end) as chunk
FROM splitter_cte) as t1
)
SELECT substring(chunk, 0, pos) as keyName,
substring(chunk, pos+1, 8000) as keyValue
FROM pair_cte
)
GO
declare #queryString varchar(2048)
set #queryString = 'foo=bar&temp=baz&key=value';
SELECT *
FROM dbo.SplitQueryString(#queryString)
OPTION(MAXRECURSION 0);
when run produces the following output.
keyName keyValue
------- --------
foo bar
temp baz
key value
(3 row(s) affected)
I believe that this will do exactly what you are asking.
SQL FIDDLE DEMO
If the order of the values in the html string remains same i would suggest using the whole string name like
select ( SUBSTRING(#qstr,CHARINDEX('empemail=',#qstr)+1,CHARINDEX('&empid=',#qstr)-CHARINDEX('empemail=',#qstr)-1)))
If you are still looking for nth occurance then refer to this link
Declare #qstr as varchar(max)='hireteammember.aspx?empemail=kuldeep#asselsolutions.com&empid=376&empname=kuldeep&adminname=TMA1&term=5&teamid=161&contactid=614¥1&WP=100¥5¥Months&Amt=500&DueDay=5&StrDt=12/31/2013&MemCatg=Employees&StrTm=21:05&PlnHrs=5&WrkDays=true¥true¥true¥true¥true¥false¥false'
(select ( SUBSTRING(#qstr,CHARINDEX('&empname=',#qstr)+1,CHARINDEX('&adminname=',#qstr)-CHARINDEX('&empname=',#qstr)-1)))
(select ( SUBSTRING(#qstr,CHARINDEX('?empemail=',#qstr)+1,CHARINDEX('&empid=',#qstr)-CHARINDEX('?empemail=',#qstr)-1)))
like this i have splitted and updated The whole string. Thank you All for your answers, Your answers Helped me to solve this

Tricky SQL query requiring search for contains

I have data such as this:
Inventors column in my table
Hundley; Edward; Ana
Isler; Hunsberger
Hunsberger;Hundley
Names are separated by ;. I want to write a SQL query which sums up the count.
Eg. The result should be:
Hundley 2
Isler 1
Hunsberger 2
Edward 1
Ana 1
I could do a group by but this is not a simple group by as you can see. Any ideas/thoughts on how to get this output?
Edit: Changed results so it doesn't create any confusion that a row only contains 2 names.
You can take a look at this. I certainly do not recommend this way if you have lots of data, BUT you can do some modifications and use it and it works like a charm!
This is the new code for supporting unlimited splits:
Declare #Table Table (
Name Nvarchar(50)
);
Insert #Table (
Name
) Select 'Hundley; Edward; Anna'
Union Select 'Isler; Hunsberger'
Union Select 'Hunsberger; Hundley'
Union Select 'Anna'
;
With Result (
Part
, Remained
, [Index]
, Level
) As (
Select Case When CharIndex(';', Name, 1) = 0
Then Name
Else Left(Name, CharIndex(';', Name, 1) - 1)
End
, Right(Name, Len(Name) - CharIndex(';', Name, 1))
, CharIndex(';', Name, 1)
, 1
From #Table
Union All
Select LTrim(
Case When CharIndex(';', Remained, 1) = 0
Then Remained
Else Left(Remained, CharIndex(';', Remained, 1) - 1)
End
)
, Right(Remained, Len(Remained) - CharIndex(';', Remained, 1))
, CharIndex(';', Remained, 1)
, Level
+ 1
From Result
Where [Index] <> 0
) Select Part
, Count(*)
From Result
Group By Part
Cheers
;with cte as
(
select 1 as Item, 1 as Start, CHARINDEX(';',inventors, 1) as Split, Inventors from YourInventorsTable
union all
select cte.Item+1, cte.Split+1, nullif(CHARINDEX(';',inventors, cte.Split+1),0), inventors as Split
from cte
where cte.Split<>0
)
select rTRIM(lTRIM(SUBSTRING(inventors, start,isnull(split,len(inventors)+1)-start))), count(*)
from cte
group by rTRIM(lTRIM(SUBSTRING(inventors, start,isnull(split,len(inventors)+1)-start)))
You can create a split function to split the col values
select splittedValues.items,count(splittedValues) from table1
cross apply dbo.split(col1,';') splittedValues
group by splittedValues.items
DEMO in Sql fiddle
first make one function who take your comma or any other operator(;) separated string into one table and by using that temp table, apply GROUP function on that table.
So you will get count for separate value.
"select d.number,count(*) from (select number from dbo.CommaseparedListToTable('Hundley;Edward;Ana;Isler;Hunsberger;Hunsberger;Hundley',';'))d
group by d.number"
declare #text nvarchar(255) = 'Edward; Hundley; AnaIsler; Hunsberger; Hunsberger; Hundley ';
declare #table table(id int identity,name varchar(50));
while #text like '%;%'
Begin
insert into #table (name)
select SUBSTRING(#text,1,charindex(';',#text)-1)
set #text = SUBSTRING(#text, charindex(';',#text)+1,LEN(#text))
end
insert into #table (name)
select #text
select name , count(name ) counts from #table group by name
Output
name count
AnaIsler 1
Hundley 2
Hunsberger 2
Edward 1

Spliting a column that is a variable/value pair, and assigning a var in sql

I have a query like:
SELECT ...
FROM ...
WHERE .. AND SomeID = #someID
I'm inheriting this massive stored procedure that has some dynamic elements to it, so I need to get the value of someID from a column in another table i.e. perform a lookup.
How can I do that?
The other column looks like:
TypeValue
'SomeID=1232,OtherID=3383'
Some the column TypeValue is VARCHAR(1000), and it contains a comma seperated string of type & value pairs.
So I need to split on the , and then split on the = so somehow get:
SET #SomeID = SELECT TypeValue FROM MyTABLE WHERE ..
How can I do this?
(note, this is sql server 2000)
Assuming you're stuck with bad design, this doesn't require dynamic SQL:
USE tempdb;
GO
CREATE TABLE dbo.foo(ID INT, TypeValue VARCHAR(1000));
INSERT dbo.foo SELECT 1, 'SomeID=1232,OtherID=3383';
INSERT dbo.foo SELECT 2, 'Blat=prong,SomeID=1254';
INSERT dbo.foo SELECT 3, 'Foo=bar,x=23';
INSERT dbo.foo SELECT 4, 'SomeID=767';
INSERT dbo.foo SELECT 5, 'x=y,SomeID=126,OtherID=3383';
SELECT ID, Value = SUBSTRING(TypeValue,
CHARINDEX('SomeID', TypeValue) + 7,
COALESCE(NULLIF(CHARINDEX(',', SUBSTRING(TypeValue,
CHARINDEX('SomeID', TypeValue) + 8, 1000)), 0), 1000))
FROM dbo.foo
WHERE ',' + TypeValue LIKE '%,SomeID=%';
Results:
ID Value
--- -----
1 1232
2 1254
4 767
5 126
If you know which row you want:
DECLARE #ID INT, #Param VARCHAR(32);
SET #ID = 5;
SET #Param = 'SomeID';
DECLARE #val INT;
SELECT #val = SUBSTRING(TypeValue,
CHARINDEX(#Param, TypeValue) + LEN(#Param) + 1,
COALESCE(NULLIF(CHARINDEX(',', SUBSTRING(TypeValue,
CHARINDEX(#Param, TypeValue) + LEN(#Param) + 2, 1000)), 0), 1000))
FROM dbo.foo
WHERE ID = #ID
AND ',' + TypeValue LIKE '%,' + #Param + '=%';
PRINT #val;
Result:
126
This doesn't guard against someone putting a string into the SomeID value, of course, so may be safer to only convert to an INT if it is proven to be numeric. But you get the point.
Using split: http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/01/t-sql-split-function.aspx
DECLARE #Str NVARCHAR(4000)
SELECT #Str = 'SomeID=1232,OtherID=3383'
SELECT * into #temp FROM [dbo].[Split] (#Str, ',')
select property = (select Data from dbo.Split((select Data from #temp where Id = b.id), '=') where Id = 1),
value = (select Data from dbo.Split((select Data from #temp where Id = b.id), '=') where Id = 2)
from #temp b
SELECT [key] = LEFT(s.value, ca.pos - 1),
[value] = SUBSTRING(s.value, ca.pos + 1, 8000)
FROM STRING_SPLIT(#activityValue, '|') s
CROSS APPLY (VALUES(CHARINDEX(':', s.value))) ca(pos);
Pulled from here: Is it possible to parse key:value pairs in SQL