SQL Substring on varying column - sql

I have a database table with a column METADATA. This METADATA may or may not contain a string. Here's the sample string:
StudentID:1234,StudentName:TestName,StudentNickName:TestNName,StudentLevel:5
Now, I want to extract the StudentNickName:TestName if it exists. Please note of the following constraint:
METADATA column doesn't always contain a value
METADATA column can contain a value without the StudentNickName clause
The StudentNickName: is fixed, while the TestNName varies per row.

For mssql 2005+
declare #t table(metadata varchar(200))
insert #t values('StudentID:1234,StudentName:TestName,StudentNickName:TestNName,StudentLevel:5')
insert #t values('')
insert #t values('StudentID:1234,StudentName:Thomas,StudentNickName:Tom,StudentLevel:3')
select left(b.a, patindex('%_,%', b.a)) StudentNickName
from #t t cross apply
(select right(metadata, patindex('%_:emaNkciNtnedutS%'
, reverse('X'+ metadata)))+',' a) b
Result:
StudentNickName
---------------
TestNName
Tom

Works in Sql Server
DECLARE #test TABLE(metadata VARCHAR(200))
INSERT #test VALUES('StudentID:1234,StudentName:TestName,StudentNickName:TestNName,StudentLevel:5')
INSERT #test VALUES('StudentID:1235,StudentName:TestName1,StudentNickName:TestNName1,StudentLevel:6')
INSERT #test VALUES('StudentID:1236,StudentName:TestName2,StudentNickName:TestNName2,StudentLevel:2')
INSERT #test VALUES('')
SELECT split.s.value('.','VARCHAR(100)') as colname FROM
(
SELECT CAST('<s>' + REPLACE(metadata,',','</s><s>') + '</s>' AS XML) col FROM #test
) AS t CROSS APPLY col.nodes('/s') AS split(s)
WHERE split.s.value('.','VARCHAR(100)') LIKE '%StudentNickName%'

Related

String split ,sort and compare with another column within a table SQL

Create Table #temp
(
Change varchar(20),
deleted_user_id int,
deleted_field_id int,
deleted_value nvarchar (4000),
inserted_user_id int,
inserted_field_id int,
inserted_value nvarchar (4000),
is_difference int,
)
insert into #temp values ('UPDATE','1', '11', '3,2,1,4','1','11','1,2,3,4','0')
insert into #temp values ('UPDATE','1', '12', '','1','12','1,2,3','0')
insert into #temp values ('UPDATE','2', '12', '1,2','2','12','','0')
select * from #temp
I am using Microsoft SQL server management studio
I am trying to compare the deleted value with inserted value. if there is a difference then set is_difference column to 1 or just return the rows.
so far I am thinking to do string split. maybe use stuff function. but not quite sure how to use all these to in a single query or is there any other option. Any help is appreciated. Thanks in advance
this query works so far.
;with cte as
(select isnull(deleted_user_id, inserted_user_id) as user_id,
isnull(deleted_field_id, inserted_field_id) as field_id,
stuff(
(
SELECT ','+ value FROM STRING_SPLIT (deleted_value, ',') group by value order by value FOR XML PATH('')
),1,1,'') as sorted_deleted_value , inserted_value
from #temp )
select * from cte where sorted_deleted_value <> inserted_value

Find rows that contain same value inside comma separated values

I have a varchar column, populated by another process where I have no control over, that is filled with comma separated values.
Now I need to find all rows where part of this column exists in that same column, in another row
example
declare #table table (value varchar(50))
insert into #table values ('NB,BD,FR'), ('BD,GK'), ('SL,SR')
select * from #table
so the table contains
value
-----
NB,BD,FR
BD,GK
SL,SR
from the example above I would like to get
value
-----
NB,BD,FR
BD,GK
Because there is a value (in this case BD but can be anything) present in both rows
Can this be done in sql?
You could use clunky XML manipulation to convert comma separated values to rows:
DECLARE #table TABLE (value VARCHAR(50));
INSERT INTO #table VALUES
('NB,BD,FR'),
('BD,GK'),
('SL,SR');
WITH cte AS (
SELECT value, node.value('.', 'varchar(10)') AS substr
FROM #table
CROSS APPLY (SELECT CAST('<x>' + REPLACE(value, ',', '</x>,<x>') + '</x>' AS XML)) AS x(doc)
CROSS APPLY doc.nodes('/x') AS n(node)
)
-- use your favorite technique to find the duplicate
SELECT value
FROM cte AS m
WHERE EXISTS (
SELECT 1
FROM cte AS x
WHERE value <> m.value AND substr = m.substr
)
The CAST(... AS XML) part assumes that your data does not contain characters that have special meaning in XML. The nodes method will convert one row to many, rest is straight forward.
This is the wrong data structure. Don't store values in strings!
declare #table table (id int, value varchar(50));
insert into #table
values (1, 'NB'), (1, 'BD'), (1, 'FR'),
(2, 'BD'), (2, 'GK'),
(3, 'SL'), (3, 'SR');
Then you can get what you want using window functions:
select id, value
from (select t.*, max(cnt) over (partition by id) as max_cnt
from (select t.*, count(*) over (partition by value) as cnt
from #table t
) t
) t
where max_cnt >= 2

how to pick string basing on ID wise

i have a table where i have values like
CREATE TABLE VALUES (ID INT,VAL VARCHAR(40))
INSERT INTO VALUES (ID,VAL)VALUES (1,'Chemicals(Sulphur4123)'),(2,'Chemicals(Sulphur4123)/RAW')
How can i get result set of :
ID Val
1 Sulphur4123
2 Sulphur4123/RAW
so far i have tried but with no luck
my code
select Substring(val,0,CHARINDEX('/',val))+ right(val,4) from values
declare #t table (ID int,value varchar(40))
insert into #t (ID,value)values (1,'Chemicals(Sulphur4123)'),(2,'Chemicals(Sulphur4123)/RAW')
select SUBSTRING(value,
CHARINDEX('(',value) + 1,
CHARINDEX(')',value) - CHARINDEX('(',value) - 1)+
+reverse(SUBSTRING(reverse(value),1,CHARINDEX('/',reverse(value))))
AS RESULT from #t
You didn't specify your database .User custom function is what you find If your database support it.
CREATE ALIAS IF NOT EXISTS f AS $$ String f(String str) {
return str.substring(str.indexOf("/"));
}$$;
SELECT ID,F(VALUE ) FROM VALUES

Iterating through a SQL Server 2008 R2 table variable and concatenate values

I have a table variable #Holding two columns: an id (not unique) and a message:
id message
---- -------
2 give
2 me
2 help
3 Need
3 help
1 help!
The result should be
2 give me help
3 Need help
1 help!
This it very much simplified, but shows that there are id which may exist more than once, and some kind of text which should be concatenated into a string.
I cannot manage it to loop through this table variable (but not through a table too!).
I tried a cursor (which I did not understand correctly) but it failed of course.
The number of records are not that much, not even 100 in that table variable.
Thanks yr. help
Michael
Original question
No CURSOR, WHILE loop, or User-Defined Function needed.
Just need to be creative with FOR XML and PATH.
[Note: This solution only works on SQL 2005 and later. Original question didn't specify the version in use.]
CREATE TABLE #YourTable ([ID] INT, [Name] CHAR(1), [Value] INT)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'A',4)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'B',8)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)
SELECT
[ID],
STUFF((
SELECT ', ' + [Name] + ':' + CAST([Value] AS VARCHAR(MAX))
FROM #YourTable
WHERE (ID = Results.ID)
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,2,'') AS NameValues
FROM #YourTable Results
GROUP BY ID
DROP TABLE #YourTable
This should work if you are using SQL Server.
select T1.id,
stuff((select ' '+T2.[message]
from #A as T2
where T1.id = T2.id
for xml path(''), type).value('.', 'varchar(max)'), 1, 1, '') as [message]
from #A as T1
group by T1.id
Pretty the same, just less letters in the code:
DECLARE #t AS TABLE ( id INT, msg VARCHAR(100) );
INSERT INTO #t
VALUES ( 2, 'give' );
INSERT INTO #t
VALUES ( 2, 'me' );
INSERT INTO #t
VALUES ( 2, 'help' );
INSERT INTO #t
VALUES ( 3, 'Need' );
INSERT INTO #t
VALUES ( 3, 'help' );
INSERT INTO #t
VALUES ( 1, 'help!' );
SELECT DISTINCT
id ,
(
SELECT ST1.msg + ' '
FROM #t ST1
WHERE ST1.id = ST2.id
FOR XML PATH('')
) t
FROM
#t ST2;

SQL scalar variable value between and

'Names' in table 'Data'
"type12pen105A"
"type12pen110A"
"type12pen121B"
Declare #n int;
select Names From Data
where Names ='type12pen'+cast(#n between 100 and 110 as varchar)+'A'
My Required out put is
"type12pen105A"
"type12pen110A"
SELECT Names
FROM Data
WHERE Names LIKE 'type12pen%'
AND CAST(SUBSTRING(Names,10,3) AS INT) BETWEEN 100 AND 110
AND RIGHT(Names,1) = 'A'
Based on the info you provided, this is ugly but it should work:
create table #data
(
names varchar(50)
)
insert into #data values('type12pen105A')
insert into #data values('type12pen101A')
insert into #data values('type12pen112A')
insert into #data values('type12pen120A')
insert into #data values('type12pen110A')
insert into #data values('type12pen106A')
insert into #data values('type12pen110C')
insert into #data values('type12pen110D')
insert into #data values('type12pen110E')
insert into #data values('type12pen121B')
SELECT Names
FROM #Data
WHERE Names LIKE 'type12pen%'
AND RIGHT(Names,1) = 'A'
AND replace(replace(names, 'type12pen', ''), 'A', '') BETWEEN 100 AND 110
drop table #data
results:
type12pen105A
type12pen101A
type12pen110A
type12pen106A
declare #Data table(
name varchar(32)
)
insert into #Data values('type12pen105A')
insert into #Data values('type12pen110A')
insert into #Data values('type12pen121B')
insert into #Data values('book11jil124C')
select name
from #Data
where cast(substring(name, 10, 3) as int) between 100 and 110
and name like 'type12pen%'
and right(name, 1) = 'A'
If this is a large table you'd probably be better served by running a process on the data and splitting the different aspects of the product name out into individual fields and querying on those. Using substring and right means you won't get the benefit of indexes.