I have records with quotations that I would like to replace with ''.
Example:
"ASKHELLO"SE --> ASKHELLO SE
""HELLO""1 --> HELLO 1
How can I do this in SQL Server?
I know replace function, but how do I get the pattern to check for to be any character other than "".
UPDATE
wordname
SET
wordname = REPLACE(deal, '"'+ '%', '')
This is incorrect. Help, please.
I am adding another answer based on your comment about double spaces on my original answer. ID in this case is arbitrary but I am huge fan of always having a primary key of some kind. XML we meet again!
--Setup the Table
DECLARE #T TABLE (wordname VARCHAR(25))
INSERT INTO #T VALUES ('"ASKHELLO"SE'),('""HELLO""1')
SELECT * FROM #T
--DECLARE AND SET XML REPLACING " with spaces
DECLARE #XML XML =
(
SELECT ROW_NUMBER() OVER (ORDER BY wordname ASC) AS "#ID",
CONVERT(XML,'<PART>' + REPLACE(CAST(CAST(REPLACE(wordname, '"',' ') AS VARCHAR(25)) AS VARCHAR(max)),' ',' </PART><PART>') + '</PART>') AS Word
FROM #T AS T
FOR XML PATH('Node'), ROOT('Nodes'), ELEMENTS, TYPE
)
SELECT #XML
--SHRED THE XML (WHICH WILL REMOVE NULLS) AND TRIM
;WITH
SHRED AS
(
SELECT ID = FieldAlias.value('(#ID)[1]','INT'),
WordName = FieldAlias.value('(Word)[1]','varchar(max)')
FROM #XML.nodes('/Nodes/Node') AS TableAlias(FieldAlias)
)
SELECT S.ID,
LTRIM(RTRIM(S.WordName)) AS WordName
FROM Shred AS S
And it should be relatively trivial for you to update off the shredded result set at this point, but let me know if you need that too. Replace the #T with your original table to pull off your data set.
REPLACE function does a global replace within a string. So u can do simple
UPDATE
wordname
SET
deal = REPLACE(deal, '"', '')
Assuming that "wordname" is your table and "deal" is a field you're replacing.
This will simple remove the double quotes. If you need to replace it with space use ' ' instead of ''
Does this help you? Try using LTRIM to strip off leading spaces after the replace. Here's a quick example based on your code:
DECLARE #T TABLE (wordname VARCHAR(25))
INSERT INTO #T VALUES ('"ASKHELLO"SE'),('""HELLO""1')
SELECT * FROM #T
SELECT LTRIM(REPLACE(wordname, '"',' '))
FROM #T
Related
I am new to SSIS. I am trying extract the data from SharePoint and load the data into SQL Server 2012. Most of the fields are coming fine except one. I am getting the unwanted values (random number and # character) like
117;#00.010;#120;#00.013
where I want to display
00.010;00.013
I tried to use below code in Derived column but still no luck
REPLACE([Related Procedure], SUBSTRING([Related Procedure], 1, FINDSTRING([Related Procedure], "#", 1)), "")
and this is the output I am getting if I use the above code
00.010;#120;#00.013
My desired output is
00.010;00.013
Please note this is using TSQL, it is not an SSIS expression. Below is a solution that will work in SQL Server 2017 or newer. The STRING_AGG function is SQL SERVER 2017 or newer and STRING_SPLIT is SQL SERVER 2016 or newer.
I use STRING_SPLIT to break apart the string by ;, then STRING_AGG to recombine the pieces you want to keep. I added another record to my example to demonstrate how you need to GROUP BY to keep the values in separate rows, otherwise all your values would come back in a single row.
CREATE TABLE #MyTable
(
Id INT IDENTITY(1,1)
, [Related Procedure] VARCHAR(100)
)
INSERT INTO #MyTable VALUES
('117;#00.010;#120;#00.013')
, ('118;#00.011;#121;#00.014')
SELECT
STRING_AGG(REPLACE([value], '#', ''), ';')
FROM
#MyTable
CROSS APPLY STRING_SPLIT([Related Procedure], ';')
WHERE
[value] LIKE '%.%'
GROUP BY
Id
Please try this:
IF (OBJECT_ID('tempdb..#temp_table') IS NOT NULL)
BEGIN
DROP TABLE #temp_table
END;
CREATE TABLE #temp_table
(
id int identity(1,1),
String VARCHAR(MAX)
)
INSERT #temp_table SELECT '117;#00.010;#120;#00.013'
;with tmp (id, value)as (
SELECT id, replace(value, '#','')
FROM #temp_table
CROSS APPLY STRING_SPLIT(String, ';')
where value like '%.%'
)
SELECT STUFF((SELECT '; ' + value -- or CAST(value AS VARCHAR(MAX)) [text()]
from tmp
where id= t.id
for xml path(''), TYPE) .value('.','NVARCHAR(MAX)'),1,2,' ') value
FROM tmp t
or since your sql server version is 2017, you can use STRING_AGG instead of STUFF to concatenate strings returned via CTE.
SELECT STRING_AGG(value, NVARCHAR(MAX)) AS csv FROM tmp group by id;
I have a select query say
select details,* from employee
details column value can like 'very good,very good, bad'. It can have any number of comma separated values.
I want to compare text that falls between each commas and remove duplicates.
Result needs to be like 'very good,bad'
How can i implement it. Please help.
Thanks in advance.
I have create a scalar valued function fn_RemoveDuplicate which takes varchar as input and return a varchar (having no duplicates).
You can then use it as
select dbo.fn_RemoveDuplicate(details),* from employee
Create FUNCTION fn_RemoveDuplicate
(
#inputstring varchar(max)
)
RETURNS varchar(max)
AS
BEGIN
declare #test2 varchar(max)
declare #test1 xml =cast(#inputstring as xml)
SET #test2 ='<Details>'+ cast(('<detail><value1>'+replace(#inputstring,',' ,'</value1></detail><detail><value1>')+'</value1></detail>') as varchar(max))+'</Details>'
set #test1=cast(#test2 as xml)
DECLARE #Details varchar(max)
SET #Details = NULL
SELECT #Details = COALESCE(#Details + ',','') + [value1]
FROM (select distinct
t.x.value('value1[1]','Varchar(50)') as value1
from #test1.nodes('/Details/detail') t(x)) as p
return #Details
END
If you use SQL Server 2016 or later the following answer solve your problem:
select
e.*,
x.[expected_result]
from
employee e
cross apply
(select
stuff((
select
distinct
','+ltrim(rtrim(value))
from
string_split(e.details, ',')
for xml path(''))
,1 ,1 ,'') as [expected_result]) as x
I solve it by using string_split() and stuff() functions. The following link helps you to understand how they work:
STRING_SPLIT (Transact-SQL)
STUFF (Transact-SQL)
SQL Server CROSS APPLY and OUTER APPLY
Storing data with comma separated value is not a good practice. I also strongly suggest you to change the model if it is possible.
The idea for the solution is to use a table valued function (fn_SplitString), and combine the resultant table based on distinct values.
The following query should do what you want:
SELECT
[ID],[Details],
[cleansedDetails] = (SELECT
STUFF((
SELECT
DISTINCT ','+LTRIM(RTRIM(ISNULL(ncValue,cvalue)))
FROM
fn_SplitString([Details], ',')
FOR XML PATH(''))
,1 ,1 ,''))
FROM [dbo].[tb_Employee]
In this db<>fiddle, you could find the DDL & DML for my example data and the definition for the table valued function fn_SplitString. You could check how the code works in different scenarios.
As the title states, I need help in converting a single row of data E.g,
col1 col2 col3 <-- This are column names
value1 value2 value3
To something like
dataResult <-- this is the column name from running the procedure or call
value1,value2,value3
The requirements are that this call ( or rather procedure) needs to be able to accept the results of sql queries of any column length and is able to convert that row to a comma delimited string format. Been stuck at this for weeks any help would be greatly appreciated...
EDIT*
Assume the unique key is the first column. Also assume that only 1 row will be returned with each query. Multiple rows will never occur.
The idea is to convert that row to a comma separated string without having to select the column names manually (in a sense automatically convert the query results)
You might try it like this:
A declared table variable to mock-up as test table. Be aware of the NULL value in col2!
DECLARE #tbl TABLE(col1 VARCHAR(100),col2 VARCHAR(100),col3 VARCHAR(100));
INSERT INTO #tbl VALUES('test1',NULL,'test3');
--This is the query:
SELECT
STUFF(
(
SELECT ',' + elmt.value('.','nvarchar(max)')
FROM
(
SELECT
(
/*YOUR QUERY HERE*/
SELECT TOP 1 *
FROM #tbl
/*--------------------*/
FOR XML AUTO ,ELEMENTS XSINIL,TYPE
)
) AS A(t)
CROSS APPLY t.nodes('/*/*') AS B(elmt)
FOR XML PATH('')
),1,1,'')
FOR XML AUTO will return each row as XML with all the values within attributes. But this would omit NULL values. Your returned string would not inlcude the full count of values in this case. Stating ELEMENT XSINIL forces the engine to include NULL values into the XML. This CROSS APPLY t.nodes('/*/*') will return all the elements as derived table and the rest is re-conactenation.
See the double comma in the middle! This is the NULL value of col2
test1,,test3
ATTENTION: You must be aware, that the whole approach will break, if there is a comma part of a (string) column...
Hint
Better was a solution with XML or JSON. Comma separated values are outdated...
Applay the next Approach:-
Use For Xml to sperate comma,
Get Columns Names Via using INFORMATION_SCHEMA.COLUMNS.
According to your need, select TOP (1) for getting First
Row.
Demo:-
Create database MyTestDB
go
Use MyTestDB
go
Create table Table1 ( col1 varchar(10), col2 varchar(10),col3 varchar(10))
go
insert into Table1 values ('Value1','Value2','Value3')
insert into Table1 values ('Value11','Value12','Value13')
insert into Table1 values ('Value21','Value22','Value23')
go
Declare #Values nVarchar(400),
#TableName nvarchar (100),
#Query nvarchar(max)
Set #TableName = 'Table1'
Select #Values = Stuff(
(
Select '+'','' + ' + C.COLUMN_NAME
From INFORMATION_SCHEMA.COLUMNS As C
Where C.TABLE_SCHEMA = T.TABLE_SCHEMA
And C.TABLE_NAME = T.TABLE_NAME
Order By C.ORDINAL_POSITION
For Xml Path('')
), 1, 2, '')
From INFORMATION_SCHEMA.TABLES As T
where TABLE_NAME = #TableName
select #Values = right(#Values,len(#Values)-4)
select #Query = 'select top(1)' + #Values + ' from ' + #TableName
exec sp_executeSQL #Query
Result:-
So I am trying to write a query which, among other things, brings back the first character in a Varchar field, then returns the first character which appears after each / character throughout the rest of the field.
The field I am refrering too will contain a group of last names, separated by a '/'. For example: Fischer-Costello/Korbell/Morrison/Pearson
For the above example, I would want my select statement to return: FKMP.
So far, I have only been able to get my code to return the first character + the first character after the FIRST (and only the first) '/' character.
So for the above example input, my select statement would return: FK
Here is the code that I have written so far:
select rp.CONTACT_ID, ra.TRADE_REP, c.FIRST_NAME, c.LAST_NAME,
UPPER(LEFT(FIRST_NAME, 1)) + SUBSTRING(c.first_name,CHARINDEX('/',c.first_name)+1,1) as al_1,
UPPER(LEFT(LAST_NAME, 1)) + SUBSTRING(c.LAST_name,CHARINDEX('/',c.LAST_name)+1,1) as al_2
from dbo.REP_ALIAS ra
inner join dbo.REP_PROFILE rp on rp.CONTACT_ID = ra.CONTACT_ID
inner join dbo.CONTACT c on rp.CONTACT_ID = c.CONTACT_ID
where
rp.CRD_NUMBER is null and
ra.TRADE_REP like '%DNK%' and
(c.LAST_NAME like '%/%' or c.FIRST_NAME like '%/%') and
ra.TRADE_FIRM in
(
'xxxxxxx',
'xxxxxxx'
)
If you read the code, it's obvious that I am attempting to perform the same concatenation on the first_name column as well. However, I realize that a solution which will work for the Last_name column (used in my example), will also work for the first_name column.
Thank you.
Some default values
DECLARE #List VARCHAR(50) = 'Fischer-Costello/Korbell/Morrison/Pearson'
DECLARE #SplitOn CHAR(1) = '/'
This area just splits the string into a list
DECLARE #RtnValue table
(
Id int identity(1,1),
Value nvarchar(4000)
)
While (Charindex(#SplitOn, #List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn+',')-1,len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Now lets grab the first character of each name and stuff it back into a single variable
SELECT STUFF((SELECT SUBSTRING(VALUE,1,1) FROM #RtnValue FOR XML PATH('')),1,0,'') AS Value
Outputs:
Value
FKMP
Here is another way to do this would be a lot faster than looping. What you need is a set based splitter. Jeff Moden at sql server central has one that is awesome. Here is a link to the article. http://www.sqlservercentral.com/articles/Tally+Table/72993/
Now I know you have to signup for an account to view this but it is free and the logic in that article will change the way you look at data. You might also be able to find his code posted if you search for DelimitedSplit8K.
At any rate, here is how you could implement this type of splitter.
declare #Table table(ID int identity, SomeValue varchar(50))
insert #Table
select 'Fischer-Costello/Korbell/Morrison/Pearson'
select ID, STUFF((select '' + left(x.Item, 1)
from #Table t2
cross apply dbo.DelimitedSplit8K(SomeValue, '/') x
where t2.ID = t1.ID
for xml path('')), 1, 0 , '') as MyResult
from #Table t1
group by t1.ID
Say I have this data:
site cell value
a b "1"
a c "2"
And I want the output for the format:
site value
a "b=1,c=2"
Is it possible with SQL?
PS: I am using access. But even if access does not support this particular syntax I would like to know any database that can.
Declare #tbl table ([site] nvarchar(100),Cell nvarchar(100),Value nvarchar(100))
INSERT INTO #tbl values('A','b','1')
INSERT INTO #tbl values('A','c','2')
SELECT [Site],
SUBSTRING(
(
select ' ,'+ Cell +'=' + CAST(value AS VARCHAR)
from #tbl b
WHERE a.[Site] = b.[Site]
FOR XML PATH('')
)
,3,100)
FROM #tbl a
GROUP BY a.[Site]
It is possible to do this in MySQL with GROUP_CONCAT