I am using following sql query
SELECT * FROM TestTable WHERE keyword IN ( Select Tags from Tags)
keyword in table are stored as keyword1, keyword2, keyword3
If it was single keyword the above query works fine but i have multiple keywords and i need to search each one of them in the
I dont thing above query is giving me right result as i am comparing
keyword1, keyword2, keyword3 with IN (keyword1, keyword2, keyword3) which wont match i tried o use instead
SELECT * FROM TestTable WHERE keyword LIKE ( Select Tags from Tags)
But it generates error
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression. The statement has been terminated.
can can i make it work so it loops through each keyword in table1, Table2 is tempTable and has these keyword1, keyword2, keyword3 in three rows
SQL FIDDLE
Fiddle is with sample data
You can do like following if you want to use pattern match.
Using EXISTS
SELECT * FROM TABLE1 T1
WHERE EXISTS
(
SELECT 1 FROM TABLE2 T2 WHERE T1.Keyword LIKE '%' + T2.keyword + '%'
)
Using JOIN
SELECT * FROM TABLE1 T1
INNER JOIN TABLE2 T2 ON T1.Keyword LIKE '%' + T2.keyword + '%'
If it is exact match, you ca do like following.
SELECT * FROM TABLE1 T1
INNER JOIN TABLE2 T2 ON T1.Keyword = T2.keyword
About your error:
Your subquery gives you multiple results and the LIKE operator cant compare more then 1 to 1. The IN operator was a good idea, but
If you are looking for something in table2 that matches EXACTLY a record (or more) in table1 this is your target:
SELECT *
FROM TABLE1
INNER JOIN TABLE2 ON TABLE2.keyword = TABLE1.keyword
If you are looking for anything in table2 that is SIMILAR to one or more records to the table1 use this:
SELECT *
FROM TABLE1
INNER JOIN TABLE2 ON TABLE2.keyword+'%' LIKE TABLE1.keyword
if you are on sql server or +, use string_split function, else :
create function split:
CREATE FUNCTION [dbo].[fn_split](
#str VARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #returnTable TABLE (idx INT PRIMARY KEY IDENTITY, item VARCHAR(8000))
AS
BEGIN
DECLARE #pos INT
SELECT #str = #str + #delimiter
WHILE LEN(#str) > 0
BEGIN
SELECT #pos = CHARINDEX(#delimiter,#str)
IF #pos = 1
INSERT #returnTable (item)
VALUES (NULL)
ELSE
INSERT #returnTable (item)
VALUES (rtrim(ltrim(SUBSTRING(#str, 1, #pos-1))))
SELECT #str = SUBSTRING(#str, #pos+1, LEN(#str)-#pos)
END
RETURN
END
Split your values like it:
select * from tmp20180308 t1 CROSS APPLY fn_split(t1.keyword, ',') t2
inner join table2 t3 on t3.keyword=t2.item
and do your joins with other table
It can be done using Dynamic SQL. Check different methods for the one that has performance advantage:
SQLFiddle:
Declare #keywords as nvarchar(max)
Declare #Sql as nvarchar(max)
select #keywords =
stuff((
select distinct ' or [Tags] like ''%' + [tags] + '%'''
from [tags]
for xml path('')
),1,3,'')
set #Sql = 'SELECT * FROM [TestTable] WHERE ' + #keywords
exec(#Sql)
Not Fiddle:
create table a (keyword varchar(20))
create table b (keyword varchar(20))
insert into a values ('the'), ( 'quick'), ( 'brown'), ( 'fox'), ( 'jumped'), ( 'over'), ( 'the'), ( 'lazy'), ( 'dog')
insert into b values ('the'), ( 'quic'), ( 'browns'), ( 'x'), ( 'jumped'), ('quick,brown,fox')
Declare #keywords as nvarchar(max)
Declare #Sql as nvarchar(max)
select #keywords =
stuff((
select distinct ' or keyword like ''%' + [keyword] + '%'''
--select distinct ' or keyword = ''' + [keyword] + '''' --if exact match is required
from b
for xml path('')
),1,3,'')
set #Sql = 'SELECT * FROM a WHERE ' + #keywords
exec(#Sql)
Related
I have a table which has a column in which I am storing a comma separated text with single quotes for each of the comma separated values. These values are employee IDs. This is how it looks
Now, I have a SQL query wherein I need to put the value from this column into a SQL IN operator. Something like this:
select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN (select CM_CONFIG_VALUE
from ADL_CONFIG_MAST_T
where CM_CONFIG_KEY like 'ATT_BIOMETRIC_OU_ID'
)
But this, does not work, the query when executed returns 0 rows whereas if I execute the query normally like below, it works.
select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN('9F3DD4B791554DDE','C9B90D62851D43AB','828CB9E6204B4DDC')
Please suggest what I should do here. I have tried using substring to remove the first and the last character as well assuming that single quotes might be the issue, but that does not work either.
select * from EMPLOYEE_MASTER where EMPLOYEEID IN(select EMPLOYEEID from ADL_CONFIG_MAST_T where CM_CONFIG_KEY like 'ATT_BIOMETRIC_OU_ID')
column should be same in where COLUMNNAME IN (select COLUMNNMAE from tablename)
You can create a temp varible and then use exec command to get the desired result.
declare #temp varchar(200)
select #temp=CM_CONFIG_VALUE
from ADL_CONFIG_MAST_T
where CM_CONFIG_KEY like 'ATT_BIOMETRIC_OU_ID'
exec('select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN (' + #temp + ')')
Try This:
DECLARE #ID VARCHAR(500);
DECLARE #Number VARCHAR(500);
DECLARE #comma CHAR;
SET #comma = ','
SET #ID = (select CM_CONFIG_VALUE
from ADL_CONFIG_MAST_T
where CM_CONFIG_KEY like %ATT_BIOMETRIC_OU_ID% + #comma);
Create table #temp (EMPLOYEEID varchar(500))
WHILE CHARINDEX(#comma, #ID) > 0
BEGIN
SET #Number = SUBSTRING(#ID, 0, CHARINDEX(#comma, #ID))
SET #ID = SUBSTRING(#ID, CHARINDEX(#comma, #ID) + 1, LEN(#ID))
Insert into #temp
select #Number
END
select *
from EMPLOYEE_MASTER
where EMPLOYEEID IN(select EMPLOYEEID from #temp)
The reason you are not getting it in your query is because your inner query returns only one row. So your query searches for '9F3DD4B791554DDE','C9B90D62851D43AB','828CB9E6204B4DDC' as as single record.
If your compatibility level is greater than or equal to 130 you can use STRING_SPLIT() function. Then your query would be
SELECT *
FROM EMPLOYEE_MASTER
WHERE EMPLOYEEID IN
(SELECT value AS empid
FROM ADL_CONFIG_MAST_T CROSS APPLY string_split(CM_CONFIG_VALUE, ',' )
WHERE CM_CONFIG_KEY LIKE 'ATT_BIOMETRIC_OU_ID' )
What this actually does is, it splits the CM_CONFIG_VALUE with ',' and returns them as rows. This is the value column I have referred. Then you use them with the IN clause.
Hope this helps!
Direct IN condition will not work here. You have split your string before searching. You can do that with XML options in SQL SERVER 2014
SELECT *
FROM EMP
WHERE EMPID IN (
SELECT a.c.value('.', 'VARCHAR(1000)')
FROM (
SELECT x = CAST('<a>' +
REPLACE(REPLACE(CM_CONFIG_VALUE , ',', '</a><a>'),'''','') + '</a>' AS XML )
FROM ADL_CONFIG_MAST_T
-- WHERE <your_condition>
) m
CROSS APPLY x.nodes('/a') a(c))
CHECK DEMO HERE
For the version 2016 and above you can use STRING_SPLIT with Compatibility level 130
I generate comma seperated string and add single quite to each numbers
Here is how i do it
DECLARE #IDs NVARCHAR(max)
SELECT #IDs = COALESCE(#IDs +',', '') + ''''
+ Cast([mynos] AS NVARCHAR(255)) + ''''
FROM mytable
WHERE id = 22
If i print variable #IDs then i get below output
'78888','3333','1222'
When i use same variable in this query then query doesnt return any value
SELECT *
FROM table1
WHERE ids IN ( #IDs )
How to fix this?
It doesn't work as your query is effectively doing this:
SELECT *
FROM TABLE
WHERE Ids IN ('''78888'',''3333',''1222''');
Which would also be equivalent to:
SELECT *
FROM TABLE
WHERE Ids = '''78888'',''3333',''1222''';
If you want to do the query as you have done, you'll need to split your delomited data out again. As you're using SQL Server 2012, you can't make use of STRING_SPLIT, so you'll need to a different one; such as Jeff Moden's DelimitedSplit8K. Then you can do:
SELECT *
FROM TABLE
WHERE IDs IN (SELECT items
FROM dbo.DelimitedSplit8K (#IDs,','));
However, why are you not simply doing...
SELECT *
FROM TABLE T
WHERE EXISTS (SELECT 1
FROM myTable mT
WHERE mT.Id = 22
AND mT.myNos = T.Ids);
You can use dynamic query #id is string variable not multi-value argument
DECLARE #IDs nVARCHAR(MAX)
SELECT #IDs = COALESCE(#IDs +',' ,'') + '''' + CAST([myNos] AS nVARCHAR(255)) + ''''
FROM myTable WHERE Id = 22
DECLARE #query nVARCHAR(MAX)
SET #query = "Select * from table1 where Ids in ("+#IDs+")"
EXECUTE sp_executesql #query
I tried below and it worked
select * from table1 where id in (select mynos from mytable where id = 22)
Thanks to #Larnu for giving me idea
Trying to replace some strings on my database where I've got two tables. The replacement on table_2 uses the results of the first replacement as an input:
Current state (string is only a stand-in, it can be anything, the important part is the dash):
|table_1 - col1| |table_2 - col1 |
---------------- ------------------------------
|string-1 | |text string-1 text string-3 |
|string-2 | |text string-3 string-2 t-ext|
|string-3 | |string-2 text string-3 te-xt|
Desired Result:
|table_1 - col1 | |table_2 - col1 |
----------------- ------------------------------
|string_1 | |text string_1 text string_3 |
|string_2 | |text string_3 string_2 t-ext|
|string_3 | |string_2 text string_3 te-xt|
Simply put I want to replace the - with _ in table_1 and also perform a corresponding replacement on table_2.
Came up with the first part, but I can't figure out the replacement part on table_2:
SELECT col1, REPLACE(col1, '-', '_') as Replacement
FROM table_1
where col1 like '%-%'
I need to do something like this (this code is INCORRECT):
SELECT REPLACE(col1,
SELECT [col1] FROM [table_1] where col1 like '%-%',
SELECT REPLACE([col1], '-', '_') FROM [table_1] where col1 like '%-%')
from table_2
For no more then 2 replacements
SELECT t2.col2, REPLACE(REPLACE(t2.col2,t1.col1,REPLACE(t1.col1, '-', '_')),t3.col1,REPLACE(t3.col1, '-', '_'))
FROM table_2 t2
JOIN table_1 t1 ON t2.col2 like '%' +t1.col1+'%' AND t1.col1 LIKE '%-%'
LEFT JOIN table_1 t3 ON t3.col1 <> t1.col1 AND t2.col2 LIKE '%'+t3.col1+'%' AND t3.col1 LIKE '%-%'
WHERE t2.col2 LIKE '%-%'
This is fully ad-hoc, no recursion needed:
DECLARE #table_1 TABLE(ID INT IDENTITY,col1 VARCHAR(100));
INSERT INTO #table_1 VALUES
('string-1'),('string-2'),('string-3');
DECLARE #table_2 TABLE(ID INT IDENTITY,col1 VARCHAR(100));
INSERT INTO #table_2 VALUES
('text string-1 text string-3'),('text string-3 string-2 t-ext'),('string-2 text string-3 te-xt');
--The first CTE replaces the value in t1
WITH t1New AS
(
SELECT ID AS t1_ID
,t1.col1 AS t1c1
,REPLACE(t1.col1,'-','_') AS new_t1c1
FROM #table_1 AS t1
)
--The second CTE splits the strings of t2 on the blanks
,t2Splitted AS
(
SELECT ID
,col1 AS t2c1
,CAST('<x>' + REPLACE(t2.col1,' ','</x><x>') + '</x>' AS XML) AS Casted
FROM #table_2 AS t2
)
--This CTE maps the values to the splitted parts
,Mapped AS
(
SELECT t1New.*
,t2Splitted.ID AS t2_ID
,ROW_NUMBER() OVER(PARTITION BY t2Splitted.ID ORDER BY (SELECT NULL)) AS PartIndex
,part.value('.','nvarchar(max)') AS Part
FROM t2Splitted
CROSS APPLY t2Splitted.Casted.nodes('/x') AS A(part)
LEFT JOIN t1New ON t1New.t1c1=part.value('.','nvarchar(max)')
)
--If there is a mapping, the new value is taken, else take the old value
,NewValues AS
(
SELECT *
,CASE WHEN t1c1 IS NOT NULL THEN new_t1c1 ELSE Part END AS newValue
FROM Mapped
)
--The final CTE re-concatenates the string with blanks in the original order
,Final AS
(
SELECT nv1.t2_ID
,(SELECT ' ' + nv2.newValue
FROM NewValues AS nv2
WHERE nv2.t2_ID=nv1.t2_ID
ORDER BY PartIndex
FOR XML PATH('')) AS FinalValue
FROM NewValues AS nv1
GROUP BY nv1.t2_ID
)
--This last value is used to update the original table
UPDATE t2 SET t2.col1=Final.FinalValue
FROM #table_2 AS t2
INNER JOIN Final ON Final.t2_ID=t2.ID
What's up to you: UPDATE t1, that's a one-liner and get rid of the trailing space in FinalValue :-)
SELECT * FROM #table_2
Variable based replacement can be done as replacing with a table.
DECLARE #Raw NVARCHAR(MAX) = '...';
SELECT #Raw= REPLACE(#Raw, P, R)
FROM (VALUES ('string-1', 'string_1'),
('string-2','string_2'),
('string-3','string_3'),
('string-4','string_4'),
) AS T(P, R);
To execute the same logic against table, think about some statements like
SELECT col1, MultipleReplace(col1, replacement_table(P, R))
FROM some_table
So create a function that accepts a string input and a replacement table. In order to pass table to function, we have to create a table type.
CREATE TYPE dbo.MulReplacements AS TABLE
(
Pattern NVARCHAR(MAX) NOT NULL,
Replacement NVARCHAR(MAX) NOT NULL
)
Then the function would be
CREATE FUNCTION dbo.MulReplace(
#string AS NVARCHAR(MAX),
#replacements AS dbo.MulReplacements READONLY
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #result AS NVARCHAR(MAX) = #string;
SELECT #result = REPLACE(#result, R.Pattern, R.Replacement)
FROM #replacements AS R;
RETURN #result;
END
Put all together
DECLARE #replacement AS dbo.MulReplacements;
INSERT INTO #replacement
SELECT col1, REPLACE(col1, '-', '_')
FROM (VALUES ('string-1'), ('string-2'), ('string-3')) AS table_1(col1)
SELECT col1, dbo.Mulreplace(col1, #replacement)
FROM (VALUES ('text string-1 text string-3'), ('text string-3 string-2 t-ext'), ('string-2 text string-3 te-xt')) AS table_2(col1)
One way of doing it with Dynamic query. Replace the actual table name and column names (commented where to change).
DECLARE #colNames VARCHAR(MAX) = ''
SELECT #colNames = #colNames + ', [' + table1_Col1 + ']' FROM tableName1 -- Table1 Column and Table1 Name
DECLARE #ReqColNames VARCHAR(MAX) = STUFF(#colNames, 1, 1, '')
DECLARE #int int
SELECT #int = count(*) FROM tableName1 -- Table1 Name
DECLARE #replace varchar(max) = replicate('REPLACE(', #int) + 't2.table2_Col2' -- Table2 Column
DECLARE #replaceCols varchar(max) = ''
SELECT #replaceCols = #replaceCols + ', r.[' + table1_Col1 + '], replace(r.[' + table1_Col1 + '], ''-'', ''_''))' FROM tableName1 -- Table1 Column and Table1 Name
DECLARE #ReplaceString varchar(max) = #replace + #replaceCols
DECLARE #cmd varchar(max) = 'SELECT ' + #ReplaceString + ' FROM
(
SELECT * FROM tableName1
PIVOT
(MAX (table1_Col1) FOR table1_Col1 IN (' + #ReqColNames + ')) x
) r
CROSS JOIN tableName2 t2'
EXEC(#cmd)
Static Query: for above code (to show what the above dynamic code is generating):
Select replace(replace(replace(t2.table2_Col2
, r.[string-1], replace(r.[string-1], '-', '_'))
, r.[string-2], replace(r.[string-2], '-', '_'))
, r.[string-3], replace(r.[string-3], '-', '_'))
from
(
Select * from tableName1
PIVOT
(MAX (table1_Col1) FOR table1_Col1 IN ([string-1], [string-2], [string-3])) x
) r
CROSS JOIN tableName2 t2
Output:
text string_1 text string_3
text string_3 string_2 t-ext
string_2 text string_3 te-xt
I am trying to REPLACE multiple characters in SQL Server query and want to achieve this via #temp table instead of nested REPLACE. I got SQL code below and want to achieve result like
ABC DEF GHI
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL DROP TABLE #temp2
CREATE TABLE #temp
(
STRING_TO_REPLACE NVARCHAR(5)
)
INSERT INTO #temp (STRING_TO_REPLACE)
VALUES (' ')
,('/')
,('_')
CREATE TABLE #temp2
(
STRING_NAME NVARCHAR(5)
)
INSERT INTO #temp2 (STRING_NAME)
VALUES ('A BC')
,('D/EF')
,('G_HI')
SELECT REPLACE(t2.STRING_NAME,(SELECT t1.STRING_TO_REPLACE
FROM #temp t1),'')
FROM #temp2 t2
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL DROP TABLE #temp2
I can achieve result with nested replace
SELECT REPLACE(REPLACE(REPLACE(t2.STRING_NAME,'_',''),'/',''),' ','') FROM #temp2 t2
but would really like to do this via #temp table. Please can someone help me on this.
When I try to run my first code I get the following error
Msg 512, Level 16, State 1, Line 23 Subquery returned more than 1
value. This is not permitted when the subquery follows =, !=, <, <= ,
, >= or when the subquery is used as an expression.
Here is one way using CROSS APPLY
SELECT result
FROM #temp2 t2
CROSS apply (SELECT Replace(string_name, t1.string_to_replace, '') AS
result
FROM #temp t1) cs
WHERE result <> string_name
Result :
result
-----
ABC
DEF
GHI
Note : This will work only if the each string_name has only one string_to_replace
Update : To handle more than one string_to_replace in a single string_name here is one way using Dynamic sql
I have made one small change to the #temp table by adding a identity property to loop
IF Object_id('tempdb..#temp') IS NOT NULL
DROP TABLE #temp
IF Object_id('tempdb..#temp2') IS NOT NULL
DROP TABLE #temp2
CREATE TABLE #temp
(
id INT IDENTITY(1, 1),
string_to_replace NVARCHAR(5)
)
INSERT INTO #temp
(string_to_replace)
VALUES (' '),
('/'),
('_')
CREATE TABLE #temp2
(
string_name NVARCHAR(5)
)
INSERT INTO #temp2
(string_name)
VALUES ('A BC'),
('D/EF'),
('G_HI'),
('A BD_')
DECLARE #col_list VARCHAR(8000)= '',
#sql VARCHAR(max),
#cntr INT,
#inr INT =1,
#STRING_TO_REPLACE NVARCHAR(5)
SELECT #cntr = Max(id)
FROM #temp
SET #sql = 'select '
WHILE #inr < = #cntr
BEGIN
SELECT #STRING_TO_REPLACE = string_to_replace
FROM #temp
WHERE id = #inr
IF #inr = 1
SET #col_list = 'replace (STRING_NAME,'''
+ #STRING_TO_REPLACE + ''','''')'
ELSE
SET #col_list = 'replace (' + #col_list + ','''
+ #STRING_TO_REPLACE + ''','''')'
SET #inr+=1
END
SET #sql += ' from #temp2'
--print #col_list
SET #sql = 'select ' + #col_list + ' as Result from #temp2'
--print #sql
EXEC (#sql)
Result :
Result
------
ABC
DEF
GHI
ABD
The multiple replace can be achieved via a recursive CTE as per following example:
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL DROP TABLE #temp2
CREATE TABLE #temp
(
STRING_TO_REPLACE NVARCHAR(10)
,Pattern NVARCHAR(10)
)
INSERT INTO #temp (STRING_TO_REPLACE, Pattern)
VALUES (' ', '% %')
,('/', '%/%')
,('_', '%[_]%') ;
CREATE TABLE #temp2
(
STRING_NAME NVARCHAR(10)
);
INSERT INTO #temp2 (STRING_NAME)
VALUES ('A BC')
,('D/EF_F E')
,('G_HI')
,('XYZ');
WITH CTE_Replace AS
(
SELECT STRING_NAME AS OriginalString
,CAST(STRING_NAME AS NVARCHAR(10)) AS ReplacedString
,CAST('' AS NVARCHAR(10)) AS StringToReplace
,1 AS ReplaceCount
FROM #temp2 ancor
UNION ALL
SELECT CTE_Replace.OriginalString
,CAST(REPLACE(CTE_Replace.ReplacedString, rep.STRING_TO_REPLACE, '') AS NVARCHAR(10)) AS ReplacedString
,CAST(rep.STRING_TO_REPLACE AS NVARCHAR(10)) AS StringToReplace
,CTE_Replace.ReplaceCount + 1 AS ReplaceCount
FROM #temp rep
INNER JOIN CTE_Replace ON CTE_Replace.ReplacedString LIKE rep.Pattern
)
,CTE_FinalReplacedString AS
(
SELECT OriginalString
,ReplacedString
,ReplaceCount
,ROW_NUMBER() OVER (PARTITION BY OriginalString ORDER BY ReplaceCount DESC) AS [Rank]
FROM CTE_Replace
)
SELECT *
FROM CTE_FinalReplacedString
WHERE [Rank] = 1
Note that #temp table was updated to include an extra column called Pattern, this column contains the search pattern to use in order to find the specific strings that has to be replaced. This was also done to simplify the join statement in the recursive CTE. Also note that in order to find the _ character the search pattern had to be updated as '%[_]%'. The reason for this is because SQL Server will interpret the _ character as a wild character instead of a specific character we are trying to find.
replace in the table is probably easier here
update t2
set t2.string_name = Replace(t2.string_name, t1.string_to_replace, '')
from #temp2 t2
cross join #temp1 t1
A simple way to deal with this is to download a copy of PatExclude8K, a T-SQL function designed for exactly this type of task. Here's a couple examples:
-- remove all non-aplphabetical characters
SELECT NewString FROM #temp2 CROSS APPLY dbo.PatExclude8K(STRING_NAME,'[^A-Z]');
-- remove all spaces, forward slashes and underscores
SELECT NewString FROM #temp2 CROSS APPLY dbo.PatExclude8K(STRING_NAME,'[ /_]');
Both queries produce this result set:
NewString
------------
ABC
DEF
GHI
I've found below code on stackoverflow which seems more near to what I'm trying to achieve but am struggling that how can I use this with my code
declare #String varchar(max) = '(N_100-(6858)*(6858)*N_100/0_2)%N_35'
--table containing values to be replaced
create table #Replace
(
StringToReplace varchar(100) not null primary key clustered
,ReplacementString varchar(100) not null
)
insert into #Replace (StringToReplace, ReplacementString)
values ('+', '~')
,('-', '~')
,('*', '~')
,('/', '~')
,('%', '~')
,('(', '~')
,(')', '~')
select #String = replace(#String, StringToReplace, ReplacementString)
from #Replace a
select #String
drop table #Replace
EDIT by gofr1
CREATE FUNCTION replacement
(
#String nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE #Replace TABLE (
StringToReplace nvarchar(100),
ReplacementString nvarchar(100)
)
INSERT INTO #Replace (StringToReplace, ReplacementString)
VALUES ('+', '~')
,('-', '~')
,('*', '~')
,('/', '~')
,('%', '~')
,('(', '~')
,(')', '~')
SELECT #String = replace(#String, StringToReplace, ReplacementString)
FROM #Replace
RETURN #String
END
GO
Then call it:
SELECT dbo.replacement ('A B-C/d')
Output:
A B~C~d
Another way with recursive CTE (full batch below):
--Create a sample table, you should use YourTable
CREATE TABLE #temp2 (
STRING_NAME NVARCHAR(max)
)
INSERT INTO #temp2 (STRING_NAME)
VALUES ('A BC'),('D/EF'),('G_HI'),('J_K/L_'),('MNO')
--I add some more objects here
The main query:
;WITH replacement AS (
SELECT *
FROM (VALUES (' '),('/'),('_')
) as t(STRING_TO_REPLACE)
), cte AS (
SELECT STRING_NAME,
STRING_NAME as OriginalString,
ROW_NUMBER() OVER (ORDER BY STRING_NAME) as rn,
1 as [Level]
FROM #temp2 t2
UNION ALL
SELECT REPLACE(c.STRING_NAME,t.STRING_TO_REPLACE,'~'),
c.OriginalString,
c.rn,
[Level]+1
FROM cte c
INNER JOIN replacement t
ON CHARINDEX(t.STRING_TO_REPLACE,c.STRING_NAME,0) > 0
)
SELECT TOP 1 WITH TIES OriginalString,
STRING_NAME
FROM cte
ORDER BY ROW_NUMBER() OVER (PARTITION BY rn ORDER BY [Level] DESC)
OPTION (MAXRECURSION 0)
Output:
OriginalString STRING_NAME
A BC A~BC
D/EF D~EF
J_K/L_ J~K~L~
G_HI G~HI
MNO MNO
Table 1:
Id | Name
1 | Example1
2 | Example2
Table 2:
Id | Table1_IDs
1 | 1,2
2 | 2
I want to select table1 from table2 using table1_IDs like:
select *
from table1
where id in (select t.table1_IDs from table2 t)
You can build query string end then use sp_executesql stored procedure to run it. Something like this (not tested)
declare #ids varchar(2000)
select #ids = coalesce(#ids + ',', '') + convert(varchar(100), table1_IDs)
from table2
declare #query nvarchar(2000) = 'select * from table1 where id in (' + #ids + ')'
execute sp_executesql #query
But this is not good idea to use coma separated values becaouse it decrease perfomance. Try to refactor yours tables.
Any other options with same structure?
select * from table1 ta join
(
SELECT id,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Certs
from (
SELECT id,CAST('<XMLRoot><RowData>' + REPLACE(value,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM table2
) t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)) b on b.id=ta.id
break table2 comma delemeted into rows and use with Table1 in Join.