I have two columns in a table. I want to merge them into a single column, but the merge should be done taking alternate characters from each columns.
For example:
Column A --> value (1,2,3)
Column B --> value (A,B,C)
Required result - (1,A,2,B,3,C)
It should be done without loops.
You need to make use of the UNION and get a little creative with how you choose to alternate. My solution ended up looking like this.
SELECT ColumnA
FROM Table
WHERE ColumnA%2=1
UNION
SELECT ColumnB
FROM TABLE
WHERE ColumnA%2=0
If you have an ID/PK column that could just as easily be used, I just didn't want to assume anything about your table.
EDIT:
If your table contains duplicates that you wish to keep, use UNION ALL instead of UNION
Try This;
SELECT [value]
FROM [Table]
UNPIVOT
(
[value] FOR [Column] IN ([Column_A], [Column_B])
) UNPVT
If you have SQL 2016 or higher you can use:
SELECT QUOTENAME(STRING_AGG (cast(a as varchar(1)) + ',' + b, ','), '()')
FROM test;
In older versions, depending on how much data you have in your tables you can also try:
SELECT QUOTENAME(STUFF(
(SELECT ',' + cast(a as varchar(1)) + ',' + b
FROM test
FOR XML PATH('')), 1, 1,''), '()')
Here you can try a sample
http://sqlfiddle.com/#!18/6c9af/5
with data as (
select *, row_number() over order by colA) as rn
from t
)
select rn,
case rn % 2 when 1 then colA else colB end as alternating
from data;
The following SQL uses undocumented aggregate concatenation technique. This is described in Inside Microsoft SQL Server 2008 T-SQL Programming on page 33.
declare #x varchar(max) = '';
declare #t table (a varchar(10), b varchar(10));
insert into #t values (1,'A'), (2,'B'),(3,'C');
select #x = #x + a + ',' + b + ','
from #t;
select '(' + LEFT(#x, LEN(#x) - 1) + ')';
How do I replace consecutive commas in a column with single comma in MS SQL?
For example, I have data like
a,,,,b,,,c,,,,,,
d,e,,,f,,,,,,g,,
I want this to be processed to following format:
a,b,c,
d,e,f,g,
The suggested duplicate, Use SQL to Replace Multiple Commas in a String with a Single Comma, is for Oracle. This is a question about SQL Server.
You could use simple REPLACE:
SELECT c, REPLACE(REPLACE(REPLACE(c, ',', '~,'), ',~', ''), '~,', ',')
FROM tab;
DBFiddle Demo
Output:
┌──────────────────┬──────────┐
│ c │ result │
├──────────────────┼──────────┤
│ a,,,,b,,,c,,,,,, │ a,b,c, │
│ d,e,,,f,,,,,,g,, │ d,e,f,g, │
└──────────────────┴──────────┘
Please note that this approach does not depend on SQL dialect and should work with MySQL/Oracle/PostgreSQL/...
It's quite easy to do it with CTE:
declare #s varchar(20) = 'a,,,,b,,,c,,,,,, d,e,,,f,,,,,,g,,'
;with cte as (
select replace(#s, ',,', ',') [s], 1 [rn]
union all
select replace(s, ',,', ',') [s], [rn] + 1
from cte
where LEN(s) - LEN(replace(s, ',,', '')) > 0
)
select top 1 #s = s from cte
order by rn desc
select #s
Although there are very good answers (personally I'd tend to lad2025) I'd like to post another approach (especially as extension to the answer by DruvJoshi)
DECLARE #tbl TABLE(s VARCHAR(100))
INSERT INTO #tbl VALUES('d,e,,,f,,,,,,g,,')
,('a,,,,b,,,c,,,,,,');
SELECT CAST('<x>'+REPLACE(s,',','</x><x>')+'</x>' AS XML)
.query('for $x in /x[text()]
return
<x>
{
concat($x, ",")
}
</x>
')
.value('.','nvarchar(max)') AS result
FROM #tbl;
Short explanation:
The solution uses the well-known XML trick to split a string. The rest is XQuery. The predicate /x[text()] will reduce the nodes to the ones with content. They will be re-created with a comma appended. The .value() with an XPath of . will return one single string of all content within the XML.
please use
SELECT
REGEXP_REPLACE(
REGEXP_REPLACE('Hi,,How are you? Fine, thanks ,, , ,,,, , James,Arden.', ', | ,', ','), --Replace ', ' and ' ,' with ','
',{1,}', ', ') single_comma_text --Replace one or more comma with comma followed by space
FROM DUAL;
Try this Script which eliminates space,multiple commas and give single comma separated as result
DECLARE #tbl AS TABLE (data nvarchar(max))
INSERT INTO #tbl
SELECT 'a,,,,b,,,c,,,,,, ,,,, ,,, ,, ,,,,,d,,,,,,,, ,, d,e,,,f,,,,,,g,,'
;WITH CTE
AS
(
SELECT data
,CAST(LEFT(data,1) AS VARCHAR(10)) AS Letter
,RIGHT(Data,LEN(Data)-1) AS Remainder
FROM #tbl
WHERE LEN(data)>1
UNION ALL
SELECT data
,CAST(LEFT(Remainder,1) AS VARCHAR(10)) AS Letter
,RIGHT(Remainder,LEN(Remainder)-1) AS Remainder
FROM CTE
WHERE LEN(Remainder)>0
)
SELECT STUFF((SELECT ', '+ Letter
FROM
(
SELECT Letter
FROM CTE
WHERE Letter <>',' AND Letter <>''
)dt FOR XML PATH ('')),1,1,'') AS RequiredOutPut
Result
RequiredOutPut
------------------
a, b, c, d, d, e, f, g
Demo : http://rextester.com/VEZS31565
If you can have unknown number of commas I'd recommend splitter using XML path like below.
Assuming you have a table T with column c
also see working demo
Explanation is inline as comments
/* first we split out each letter from each column using XML Path after replacing commas with empty nodes */
; with cte as (
select
id,s
from
(
select
id,
xmldata=cast('<x>'+replace(c,',','</x><x>')+'</x>' as xml) -- conversion to XML from varchar
from t
)A
cross apply
(
select
s = data.D.value('.','varchar(100)')
FROM
A.xmldata.nodes('x') AS data(D)
)c
where s <>''-- filter out empty nodes i.e. commas
)
/* Now we join back results from CTE by adding single comma between letters*/
select distinct id, stuff
((select ','+ s
from cte c1
where c1.id =c2.id
for xml path ('')),1,1,'')
from cte c2
This is what i did.
select replace(replace(replace('a,,,b,,,c,d,e,,,,f',',','<>'),'><',''),'<>',',')
Here is the simple one to suffice all the below cases:
Removing multiple commas in starting of the string
Removing multiple commas at the end of the string
Removing multiple commas to single comma in the middle of the string
select REGEXP_REPLACE(REGEXP_REPLACE(',,LE,,EN,,A,,,','^,*|,*$',''),',{1,}', ', ');
Output :
LE, EN, A
I have a CSV field in my SQL server, which contains X-number of days.
Here's an example with numbers (to make it easier to read):
1,2,3,4
4,5,1,9
3,6,8,4
I would like to sort each line. Is there an easy way to do it?
I want to have following result:
1,2,3,4
1,4,5,9
3,4,6,8
Thanks!
That functionality is not standard in the SQL language, nor is it readily available in SQL Server.
What you could do is write a User-Defined Function (UDF) in any .NET language, then call that function in your query. The function itself would simply take a string as input, expecting a CSV value, and return the sorted version of that string. You can then query your table with that function, like so:
SELECT SortedCsv(NumbersOfDays) FROM MyTable
You can find out more about writing UDF's in .NET (C#) in this article: http://www.dotnetspider.com/resources/19679-Creating-User-Defined-Function-Using-Managed-Code.aspx and this one: http://www.diaryofaninja.com/blog/2010/09/06/hidden-gems-microsoft-sql-net-managed-code-support
Good luck!
I'd recommend that you use a programming language like python to read each line, sort it and optionally put it back into SQL.
Try this
DECLARE #CSV TABLE(RID INT,ID INT,COL_NAME VARCHAR(MAX))
INSERT INTO #CSV(RID,ID,COL_NAME)
SELECT
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY COL_NAME) AS RID
,ID,COL_NAME FROM
(
SELECT ID , Split.a.value('.', 'VARCHAR(100)') AS COL_NAME
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY COL_NAME) AS ID,
CAST ('<M>' + REPLACE(COL_NAME, ',', '</M><M>') + '</M>' AS XML) AS COL_NAME
FROM TABLE_NAME
) AS A CROSS APPLY COL_NAME.nodes ('/M') AS Split(a)
) v
SELECT COL_NAME FROM
(
SELECT DISTINCT C1.ID,
STUFF((SELECT ',' + C2.COL_NAME AS [text()] FROM #CSV C2
WHERE C2.ID = C1.ID FOR XML PATH('')),1,1,'' ) AS COL_NAME
FROM #CSV C1
) RESULT
ORDER BY COL_NAME
Replace 'COL_NAME' and 'TABLE_NAME' with your column amd table names
SQLFiddle Demo
I replace all blanks with # using this
SELECT *, REPLACE(NAME,' ','#') AS NAME2
which results miss#test#blogs############## (different number of #s dependent on length of name!
I then delete all # signs after the name using this
select *, substring(Name2,0,charindex('##',Name2)) as name3
which then gives my desired results of, for example MISS#test#blogs
However some wheren't giving this result, they are null. This is because annoyingly some rows in the sheet I have read in dont have the spaces after the name.
is there a case statement i can use so it only deletes # signs after the name if they are there in the first place?
Thanks
The function rtrim can be used to remove trailing spaces. For example:
select replace(rtrim('miss test blogs '),' ','#')
-->
'miss#test#blogs'
Example at SQL Fiddle.
try this:
Declare #t table (name varchar(100),title varchar(100),forename varchar(100))
insert into #t
values('a b c','dasdh dsalkdk asdhl','asd dfg sd')
SELECT REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(name)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS Name,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(title)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS title,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(forename)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS forename
FROM #t WHERE
(CHARINDEX(' ',NAME) > 0 or CHARINDEX(' ',title) > 0 or CHARINDEX(' ',forename) > 0)
SQL Fiddle Demo
select name2, left(name2,len(name2)+1-patindex('%[^#]%',reverse(name2)+'.'))
from (
SELECT *, REPLACE(NAME,' ','#') AS NAME2
from t
) x;
Check this SQL Fiddle
For posterity, sample table:
create table t (name varchar(100));
insert t select 'name#name#ne###'
union all select '#name#name'
union all select 'name name hi '
union all select 'joe public'
union all select ''
union all select 'joe'
union all select 'joe '
union all select null
union all select ' leading spaces'
union all select ' leading trailing ';
Don't quite understand the question, but if the problem is there is not spaces after some names, can't you do this first:
SELECT *, REPLACE(NAME+' ',' ','#') AS NAME2
i.e., add a space to all names right off the bat?
I had this same problem some days ago.
Well actually, there's a quickly way to subtract the spaces from both the begin and end inside strings. In SQL Server, you can use the RTRIM and LTRIM for this. The first one supresses spaces from right side and the second supresses from left. But, if in your scenario also may exists more than one space in the middle of the string I sugest you take a look on this post on SQL Server Central: http://www.sqlservercentral.com/articles/T-SQL/68378/
There the script's author explain, in details, a good solution for this situation.