Progress 12.2 - Concat rows with same ID - sql

I use the database Progress 12.2 and I want to group rows with same id
For example I have
ID Code
1 PB
1 RO
And I want :
ID Code
1 PB, RO
This is my request :
SELECT id, code FROM table WHERE table.id = 1
I tried String_agg, Group_concat ... but nothing works. Anyone has an idea ?
Regards,

You can use someting like that;
DECLARE #TBL TABLE (ID Int, Code nvarchar(5))
INSERT INTO #TBL values (1 ,'PB'),(1 ,'RO')
SELECT DISTINCT
T1.ID,
CONCAT_STRING = STUFF((
SELECT ',' + T2.Code
FROM #TBL T2
WHERE T2.ID = T1.ID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM #TBL T1
The result will be like this;

Related

Delete ; symbol at string end (SQL)

I have SQL script that gets roles and return string with list of roles
Here is part of code
, ISNULL(SUBSTRING(
(
SELECT ECBR.RoleName + ';' AS [text()]
FROM [External].[vw_ExecutiveChangeByRole] ECBR
WHERE ECBR.VendorExecutiveChangeId = ECH.VendorExecutiveChangeId
AND (ECBR.IsCurrentOrPrior IS NULL OR ECBR.IsCurrentOrPrior = 1)
AND ECBR.RecognizedWith = 'ML'
ORDER BY ECBR.RoleId
FOR XML PATH ('')
), 1, 1000), '') AS RecognizedCurrentRoles
And now showing like VP;Controller;
How I can make this string without last;, just VP;Controller
It depends on your version of SQL Server.
If you have a version 2017 or higher than this is very easy, see this example
let's first build some sample data
declare #t table (groupid int, name varchar(50))
insert into #t (GroupID, name)
values (1, 'VP'), (1, 'Controller'), (2,'A'), (2,NULL), (2,'whatever');
the query for sql server 2017 or higher
select t.groupid,
string_agg(t.name, ';') as name
from #t t
group by t.groupid
the result is
groupid name
------- ----
1 VP;Controller
2 A;whatever
On older versions you need to select for XLM Path and then use STUFF to get rid of the extra ;
select t.groupid,
( select ';' + t2.name
from #t t2
where t2.groupid = t.groupid
for XML PATH('')
) as without_stuff,
stuff( ( select ';' + t2.name
from #t t2
where t2.groupid = t.groupid
for XML PATH('')
),
1, 1, '') as with_stuff
from #t t
group by t.groupid
the result is
groupid without_stuff with_stuff
------- ------------- ----------
1 ;VP;Controller VP;Controller
2 ;A;whatever A;whatever
EDIT
As commented by #Charlieface the XLM PATH could return unexpected results when the character is a special XML character, for example <
lets look at this example
select t.groupid,
( select '<' + t2.name
from #t t2
where t2.groupid = t.groupid
for XML PATH('')
) as without_stuff
from #t t
group by t.groupid
it will return this result
groupid without_stuff
------- -------------
1 <VP<Controller
2 <A<whatever
I can imagine that this is not what you expected.
To solve this, alter the query like this
select t.groupid,
(select '<' + t2.name
from #t t2
where t2.groupid = t.groupid
for XML PATH(''), TYPE
).value('text()[1]','nvarchar(max)') as without_stuff
from #t t
group by t.groupid
Now the result will be more what you want
groupid without_stuff
------- -------------
1 <vp<Controller
2 <A<whatever

using recursive function to simulate group_concat

I have a table like
ID NAME
1 STALIN
2 MERWIN
1 AMALA
1 RAYON
i want the out as
ID NAME
1 STALIN,AMALA,RAYON
2 MERWIN
How can do this using recursive function
You can do this using XML Path
SELECT ID, NAME =
STUFF((SELECT ', ' + NAME
FROM your_table b
WHERE b.ID = a.ID
FOR XML PATH('')), 1, 2, '')
FROM your_table a
GROUP BY ID
Live Demo
Follow this link and see the case 3. it explains why to use XML path over recursive cursor.
You can use FOR XML PATH to get the result:
for example:
DECLARE #EXAMPLE TABLE (ID int, NAME nvarchar(10))
INSERT #EXAMPLE VALUES (1,'STALIN'),(2,'MERWIN'),(1,'AMALA'),(1,'RAYON')
SELECT
ID,
SUBSTRING(NAME,0,LEN(NAME)) AS NAME
FROM ( SELECT DISTINCT
T1.ID,
STUFF(( SELECT DISTINCT '' + t2.NAME + ','
FROM #EXAMPLE T2
WHERE T1.ID = T2.ID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
,1,0,'') NAME
FROM #EXAMPLE t1) AS info

create one row from two columns sql

How to create one row from two columns?
Example:
id description
------------------
1 one
2 two
3 three
In result:
1: one, 2: two, 3: three
I use follow statment:
select Id,
stuff((SELECT distinct ', ' + cast(Description as varchar(10))
FROM dbo.tbl t2
where t2.Id = t1.Id
FOR XML PATH('')),1,1,'')
from dbo.tbl t1
group by Id
But in result I have two columns. I need one such as string
You can try this query.
CREATE TABLE T (
id int,
description varchar(50)
);
INSERT INTO T VALUES (1,'one');
INSERT INTO T VALUES (2,'two');
INSERT INTO T VALUES (3,'three');
Query 1:
select
stuff((SELECT ', ' + CAST(t2.ID AS VARCHAR(5)) + ':'+ t2.description
FROM t t2
FOR XML PATH('')),1,1,'')
Results:
| |
|------------------------|
| 1:one, 2:two, 3:three |
i think you are asking for this
select stuff((SELECT ', ' + CAST(tbl.id AS varchar) + ':' + tbl.description
FROM tablename tbl FOR XML PATH('')), 1, 1, '') as Columnname
You were close..
declare #T TABLE (
id int,
description varchar(50)
);
INSERT INTO #T VALUES (1,'one');
INSERT INTO #T VALUES (2,'two');
INSERT INTO #T VALUES (3,'three');
select Id,
stuff((SELECT distinct ', ' + +cast(id as nvarchar) +':'+description
FROM #T t2
where t2.Id = t1.Id
FOR XML PATH('')),1,1,'')
from #T t1
group by Id
OR If you want all the ids in a sing row use the below query
select stuff((select ',' +cast(id as nvarchar) +':'+description
from #T for xml path('')),1,1,'')
select statement is like a for loop or an iterator and you you need a space to save you data and it's not possible with select only because in the moment select statement only access to a row not previous row and not next row so
please use a scaler-value function
create function test()
return
nvarchar(max)
as
begin
declare #s nvarchar(max)
select #s = concate(#s, id, description)
from yourTable
return #s
end

Get 3 rows data in 1 row

My records looks like:
aid cmpyname rid imgpath
1 abc 1 ~/img/aa.jpg:~/img/bb.jpg:~/img/cc.jpg:
2 abc 1 ~/img/dd.jpg:~/img/ee.jpg:~/img/ff.jpg:
3 xyz 2 ~/img/gg.jpg:~/img/hh.jpg:~/img/ii.jpg:
4 xyz 2 ~/img/jj.jpg:~/img/kk.jpg:~/img/ll.jpg:
What I want to get is displayed below - but in a single query
cmpyname rid imgpath
abc 1 ~/img/aa.jpg:~/img/bb.jpg:~/img/cc.jpg:~/img/dd.jpg:~/img/ee.jpg:~/img/ff.jpg:
xyz 2 ~/img/gg.jpg:~/img/hh.jpg:~/img/ii.jpg:~/img/jj.jpg:~/img/kk.jpg:~/img/ll.jpg:
How can I do so? I haven't provided any relationship so please keep it in mind.
Thanks and Regards
select max(cmpyname) as cmpyname, rid,
stuff((
select imgpath
from Records t1
where t1.rid = t2.rid
order by t1.aid
for xml path(''), type).value('.', 'varchar(max)'), 1, 0, ''
) as imgpath
from Records t2
group by rid;
http://sqlfiddle.com/#!18/46822/1
select distinct rid,imgpath,rid from(
select imgpath=(select imgpath + ', ' AS 'data()'
FROM tbl_Temp
where tbl_Temp.rid=rid FOR XML PATH('') )
,id,cmpyname,rid from tbl_Temp
) as temp
Something like this:
Just paste into into an empty query window and execute. Adapt to your needs...
DECLARE #tbl TABLE(aid INT, cmpyname VARCHAR(100), rid INT, imgpath VARCHAR(1000));
INSERT INTO #tbl VALUES
(1,'abc',1,'~/img/aa.jpg:~/img/bb.jpg:~/img/cc.jpg:')
,(2,'abc',1,'~/img/dd.jpg:~/img/ee.jpg:~/img/ff.jpg:')
,(3,'xyz',2,'~/img/gg.jpg:~/img/hh.jpg:~/img/ii.jpg:')
,(4,'xyz',2,'~/img/jj.jpg:~/img/kk.jpg:~/img/ll.jpg:');
SELECT DISTINCT tbl.cmpyname
,tbl.rid
,(
SELECT '' + x.imgpath
FROM #tbl AS x
WHERE x.rid=tbl.rid
FOR XML PATH('')
) AS allPaths
FROM #tbl AS tbl
SELECT DISTINCT B.cmpyname, B.rid,
(
SELECT imgpath + '' FROM tbl1 AS A WHERE (B.rid = A.rid) FOR XML PATH('')
) AS imgpath
FROM tbl1 AS B

How to make 2 rows into single row in sql

I have a query
example
Title Description
A XYZ
A ABC
now i want a sql query so that i can get a single row
Output :
Title Description
A XYZ | ABC
Declare #tbl table(Title nvarchar(1),[Description] nvarchar(100))
Insert into #tbl values('A','XYZ');
Insert into #tbl values('A','ABC');
Insert into #tbl values('A','PQR');
DECLARE #CSVList varchar(100)
SELECT #CSVList = COALESCE(#CSVList + ' | ', '') +
[Description]
FROM #tbl
WHERE Title='A'
SELECT #CSVList
declare #table table (i int, a varchar(10))
insert into #table
select 1, 'ABC' union all
select 1, 'XYZ' union all
select 2, '123'
select t.i,
max(stuff(d.i, 1, 1, '')) [iList]
from #table t
cross
apply ( select '|' + a
from #table [tt]
where t.i = tt.i
for xml path('')
) as d(i)
group
by t.i;
In mysql there is a group_concat function, that can help you.
Use it like this:
SELECT Title,GROUP_CONCAT(Description) FROM table_name GROUP BY Title
The output will be
Title Description
A XYZ,ABC
Then you can replace "," with "|" if you want(it can be done with replace function)
For 2 rows you can self join in SQL Server. This avoids the assorted "concatenate rows into a column" tricks. You can use a LEFT JOIN and NULL handling too for 1 or 2 rows
SELECT
T1.Title,
T1.Description + '|' + T2.Description
FROM
MyTable T1
JOIN
MyTable T2 ON T1.Title = T2.Title
SELECT
T1.Title,
T1.Description + ISNULL('|' + T2.Description, '') --COALESCE for the pedants)
FROM
MyTable T1
LEFT JOIN
MyTable T2 ON T1.Title = T2.Title
If you are using SQL Server, try this: How to return 1 single row data from 2 different tables with dynamic contents in sql