select distinct elements from two columns with comma separated in sql - sql

I have a table with two columns like this
col1 col2
a b
b a
c d
d a
I want to get distinct values of these two columns combined with comma separated.
Expected out put is like this
a,b,c,d

The following example concatenate row values into a variable
DECLARE #val nvarchar(max)
SELECT #val = COALESCE(#val + ',' + col1, col1)
FROM (SELECT col1
FROM dbo.twoColumns
UNION
SELECT col2
FROM dbo.twoColumns
) x
SELECT #val
Demo on SQLFiddle

try this , its very much easy i think
select group_concat(distinct(c)) as d
from
(
select col1 c from your_table
union
select col2 c from your_table
) as d

Related

Concatenate rows into columns (NO FOR XML PATH('') and recursive CTEs) - SQL Server 2012

I have a very particular problem at hand.
Brief introduction: I have two columns at a database that I need to "group concatenate", in MySQL I would simply use GROUP_CONCAT to get the desired result, in SQL Server 2017 and on I would use STRING_AGG, the problem that I have is in the SQL Server 2012, which doesn't have this function.
Now, under normal circumstances I would use FOR XML PATH('') to get the solution, this is not viable since I'm running the query from the editor inside a third source application, the error that I get is
FOR XML PATH('') can't be used inside a cursor
For the sake of the argument let's assume that it's completely out of question to use this function.
I have tried using recursive CTE, however, it's not viable due to execution time, UNION ALL takes too much resources and can't execute properly (I am using the data for reporting).
I will no post the screenshots of the data due to the sensitivity of the same, imagine just having two columns, one with an id (multiple same id's), and a column with the data that needs to be concatenated (some string). The goal is to concatenate the second columns for all of the same id's in the first columns, obviously make it distinct in the process.
Example:
Input:
col1 col2
1 a
1 b
2 a
3 c
Output:
col1 col2
1 a/b
2 a
3 c
Does anyone have a creative idea on how to do this?
If you know the maximum number of values that need to be concatenated together, you can use conditional aggregation:
select col1,
stuff( concat(max(case when seqnum = 1 then '/' + col2 end),
max(case when seqnum = 2 then '/' + col2 end),
max(case when seqnum = 3 then '/' + col2 end),
max(case when seqnum = 4 then '/' + col2 end),
max(case when seqnum = 5 then '/' + col2 end)
), 1, 1, ''
) as col2s
from (select t.*,
row_number() over (partition by col1 order by col2) as seqnum
from t
) t
group by col1;
You can get the maximum number using:
select top (1) count(*)
from t
group by col1;
Your sample output seems wrong as 'a/b' should come for value 2.
try the following:
declare #t table (col1 int, col2 varchar(100))
insert into #t select 1, 'a'
insert into #t select 2, 'b'
insert into #t select 2, 'a'
insert into #t select 3, 'c'
declare #final_table table (col1 int, col2 varchar(100), col2_all varchar(1000))
insert into #final_table (col1, col2)
select * from #t
declare #col2_all varchar(1000)
declare #Name sysname
update #final_table
SET #col2_all = col2_all = COALESCE(CASE COALESCE(#Name, '')
WHEN col1 THEN #col2_all + '/' + col2
ELSE col2 END, ''),
#Name = col1;
select col1, col2_grouped = MAX(col2_all)
from #final_table
group by col1
Using CTE:
;with cte(col1,col2_grouped,rn)
as
(
select col1, col2 , rn=ROW_NUMBER() over (PARTITION by col1 order by col1)
from #t
)
,cte2(col1,final_grouped,rn)
as
(
select col1, convert(varchar(max),col2_grouped), 1 from cte where rn=1
union all
select cte2.col1, convert(varchar(max),cte2.final_grouped+'/'+cte.col2_grouped), cte2.rn+1
from cte2
inner join cte on cte.col1 = cte2.col1 and cte.rn=cte2.rn+1
)
select col1, MAX(final_grouped) col2_grouped from cte2 group by col1
Please see db<>fiddle here.

Get column names from a table matching a specific value

I have a table named TableA which has many rows. Sample structure given below
CID int, Col1 int, Col2 int, Col3 int, Col4 int
when I run a query (say when CID=5) i will get only one row with Col1,Col2 etc having different values.
I want to get the digit of column name where the row value is -1.
For more clarity
CID, Col1, Col2 , Col3 , Col4
5 0 -1 0 -1
in this example i should get result as
MyRes
2
4
Is there a any way to achieve it
You may use unpivot then filter your record on basis of result value which is -1 in your case.
; with cte as (
select CID, result, col from
(
select * from table
) as t
unpivot
(
result for col in ( Col1, col2, col3, col4 )
) as p
)
select CId, col from cte where result = -1
Just a bit of homework for you to get the number part from the column name.
In case you find any problem in that part please comment I'll do that also but lets give a try first.
I got the answer
declare #ID int
set #ID = 1
select substring( T1.ColName, 2, LEN(T1.ColName)) as MyRes from (
select
Col.value('local-name(.)', 'varchar(10)') as ColName
from (select *
from TableA
for xml path(''), type) as T(XMLCol)
cross apply
T.XMLCol.nodes('*') as n(Col)
where Col.value('.', 'varchar(10)') = '-1'
)T1

Getting Unique values from a row - SQL Server

I have columns something like this:
col1 | col2 | col3 | col4 | col5 | col6 |
-----+------+------+------+------+------+
a | b | c | a | c | c
I am trying to get unique values in the column it self PER row.
So ideally, I want a,b,c to be returned
I tried doing PIVOT and applying a DISTINCT but that doesn't go well as there are other columns that I couldn't show in the question.
So is there another way that this could be obtained?
Thanks in advance
Is this what you are looking for ..?
IF OBJECT_ID('tempdb..#Pivot_data')IS NOT NULL
DROP TABLE #Pivot_data
IF OBJECT_ID('tempdb..#tab')IS NOT NULL
DROP TABLE #tab
select * into #tab from
(select 'a'AS COL1,'b'AS COL2,'c'AS COL3,'a'AS COL4,'c'AS COL5,'c' COL6)AS A
DECLARE #Columns nvarchar(max) ,#QUERY NVARCHAR(MAX)
;WITH CTE AS (
SELECT COLUMNSS,COL_VALUES,ROW_NUMBER()OVER(PARTITION BY COL_VALUES ORDER BY (SELECT 1))RN FROM (
SELECT * FROM #tab
)AS A
UNPIVOT(COL_VALUES FOR COLUMNSS IN([col1],[col2],[col3],[col4],[col5],[col6])) AS B
)
,FINAL_Result as (select COLUMNSS,COL_VALUES from CTE where RN=1)
SELECT * INTO #Pivot_data FROM FINAL_Result
SET #Columns= (SELECT STUFF((SELECT ',['+COLUMNSS+']' FROM #Pivot_data FOR XML PATH('')),1,1,''))
SET #QUERY=N'SELECT * FROM (
SELECT * FROM #Pivot_data
) AS A
PIVOT (MAX(COL_VALUES)FOR COLUMNSS IN('+#Columns+'))
AS B'
PRINT #QUERY
EXEC (#QUERY)
Logic :
From the given table i did unpivot and generated a Row_number() based on the column values and considered only which are Row_num=1 i.e Distinct columns values . and finally, i Pivoted the resultant data .
It seems to be CROSS APPLY would be work here
select a.Col from table t
cross apply (
values (t.Col1), (t.Col2), (t.Col3),
(t.Col4), (t.Col5), (t.Col6)
)a(Col)
group by a.Col
AND, do the PIVOT with your own way
Try this code
IF OBJECT_ID('tempdb..#Temptab')IS NOT NULL
DROP TABLE #Temptab
;With cte(col1 , col2 , col3 , col4 , col5 , col6 )
AS
(
SELECT 'a' , 'b' , 'c' , 'a' , 'c' , 'c'
)
SELECT DISTINCT AllColumn
INTO #Temptab FROM cte
CROSS APPLY ( VALUES (col1),( col2) , (col3) , (col4) , (col5) , (col6)
) AS A (AllColumn)
DECLARE #SqlQuery nvarchar(max)
,#Sql nvarchar(max)
SELECT #SqlQuery='SELECT DISTINCT '+STUFF((SELECT ', '+ReqColumn FROM
(
SELECT ''''+AllColumn +'''' +' AS Col'+ CAST(Seq AS VARCHAR(2)) As ReqColumn
FROm
(
SELECT ROW_NUMBER()OVER(Order by AllColumn) AS Seq,AllColumn FROM #Temptab
)dt
)dte FOR XML PATH ('')),1,1,'') +' From #Temptab'
PRINT #SqlQuery
EXEC(#SqlQuery)
Result
Col1 Col2 Col3
----------------------
a b c
You can first union all columns to get unique values and then use the GROUP_CONCAT() function in MySql or if your database is Oracle then use list_agg() function:
Please try the below SQL:
select GROUP_CONCAT(col1 SEPARATOR ', ') from (
select '1' as 'serial', col1 from pivot
union
select '1' as 'serial',col2 from pivot
union
select '1' as 'serial',col3 from pivot
union
select '1' as 'serial',col4 from pivot
union
select '1' as 'serial',col5 from pivot
union
select '1' as 'serial' ,col6 from pivot
)derived
GROUP BY serial;
Output:
Note : I have make the 'serial' column in my query to do the group by. You can use the your identifier field in group by clause if you have any.

Dynamic Comma Seperated string into different column

May someone please help me for this strange scenario. i have a data as given below.
DECLARE #TABLE TABLE
(
ID INT,
PHONE001 VARCHAR(500)
)
INSERT TEST
SELECT 1,'01323840261,01323844711' UNION ALL
SELECT 2,'' UNION ALL
SELECT 3,',01476862000' UNION ALL
SELECT 4,'01233625418,1223822583,125985' UNION ALL
SELECT 5,'2089840022,9.99021E+13'
and i am trying to put in seperate column for each comma value. the max number of column depends on the largest comma seperated string.
Expected Output
1|01323840261|01323844711|''
2|''|''|''
3|01476862000|''|''|
4|01233625418|1223822583|125985|
5|2089840022|9.99021E+13|''|
try
select id,T.c.value('t[1]','varchar(50)') as col1,
T.c.value('t[2]','varchar(50)') as col2 ,
T.c.value('t[3]','varchar(50)') as col3 from
(select id,cast ('<t>'+ replace(PHONE001,',','</t><t>') +'</t>'
as xml) x
from #TABLE) a cross apply x.nodes('.') t(c)

Grouping between consecutive rows in a table without cursor

I trying to get a grouping done between 2 rows without a cursor, can some one help me reg this
Col1(int) Col2(int)
--------- ---------
1 20
2 30
3 40
I want output like this
Col1 Col2
---- ----
1-2 50
2-3 70
Are you sure you aren't missing any rows...
Select cast(a.col1 as varchar(10)) + '-' + cast(b.col1 as varchar(10)) as col1,
a.col2 + b.Col2 as Col2
From mytable a
Inner Join mytable b on b.col1 = (a.col1 + 1)
if you might be missing rows, you might need to be more complicated.
That's a tricky one if you don't want to repeat the rows (1-2, 2-3) and you can expect there to be some missing ids (as would be normal if you have an identity field).
Try this:
CREATE TABLE #temp (id INT, value INT)
INSERT INTO #temp
SELECT 1,2
UNION ALL
SELECT 2,8
UNION ALL
SELECT 3,8
UNION ALL
SELECT 5,19
SELECT id, value, ROW_NUMBER() OVER (ORDER BY id) AS rownumber
INTO #temp2
FROM #temp
SELECT * FROM #temp2
SELECT CAST(b.id AS VARCHAR(10)) + '-' + CAST(a.id AS VARCHAR(10)) AS col1,
a.value + b.value as Col2
FROM #temp2 a
JOIN #temp2 b
ON a.rownumber = b.rownumber+1
WHERE ABS(a.rownumber)%2 = 0
Assuming that col1 is integer
SELECT CAST(a.col1 as VARCHAR(10))+ '-' + CAST(b.col1 as VARCHAR(10)), COALESCE(a.col2,0)+COALESCE(b.col2,0)
FROM table a
JOIN table b a.col1 = b.col1 + 1
you can test following query also...
I have oracle in my machine that's why I can run and say only oracle queries..
please check whether this will work on sql server also or not and tell me about ...
select * from
(Select lag (col1) over (order by col1)|| '-' || col1 as col1
col2 + lag (col2) over (order by col1) as Col2
From mytable
)
where col2 is not null;
in oracle lag () function used to fatch last row values.. and if it is first row then this function will give null values.. so that by appling addition on null values you will get null only
by this concept we will get desired output...