Delete ; symbol at string end (SQL) - 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

Related

Progress 12.2 - Concat rows with same ID

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;

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

Combine Multi Rows with COALESCE

Using SQL-Server 2012
I have the following Table:
Id Description
6192 Salzburg
6193 Salzburg
6194 Salzburg
6196 Innsbruck
6197 Innsbruck
6198 Innsbruck
6199 Innsbruck
6201 Bregenz
6202 Bregenz
6203 Bregenz
I want to Select each Distinct "Description" with all the Id's together in one string:
Description Ids
Salzburg '6192,6193,6194'
Innsbruck '6196,6197,6198'
I saw some similar code on this site [How to concatenate text from multiple rows into a single text string in SQL server?, but I couldn't figure it out yet for my purpose (don't want to use XML Path!). Here is what I have tried so far:
DECLARE #ids AS Nvarchar(MAX)
SELECT #ids = COALESCE(#ids + ',', '') + CAST(t.Id AS nvarchar(5))
FROM (SELECT tmp.Id FROM (SELECT id, [Description] FROM tblMasterPropValues WHERE IdCategory = 253 AND IsActive = 1) as tmp
WHERE [Description] = tmp.[Description]) AS t
SELECT #ids
--SELECT DISTINCT [Description], #ids AS IDs FROM tblMasterPropValues WHERE IdCategory = 253 AND IsActive = 1 AND Id IN (#ids)
I can't really get my head around it, and would appreciate any help on it.
You can try using STUFF() function
SELECT description, Ids = STUFF(
(SELECT ',' + Id
FROM tblMasterPropValues t1
WHERE t1.description = t2.description
FOR XML PATH (''))
, 1, 1, '') from tblMasterPropValues t2
group by description;
For that FOR XML PATH() is the right clause so, you can do :
SELECT DISTINCT v.description, STUFF(v1.ids, 1, 1, '''') + ''''
FROM tblMasterPropValues v CROSS APPLY
(SELECT ', '+ CAST(v1.Id AS VARCHAR(255))
FROM tblMasterPropValues v1
WHERE v1.description = v.description
FOR XML PATH('')
) v1(ids);
You can also make it by using recursive CTE
DECLARE #tblMasterPropValues TABLE (Id INT, Description VARCHAR(20))
INSERT INTO #tblMasterPropValues VALUES
(6192 , 'Salzburg'),
(6193 , 'Salzburg'),
(6194 , 'Salzburg'),
(6196 , 'Innsbruck'),
(6197 , 'Innsbruck'),
(6198 , 'Innsbruck'),
(6199 , 'Innsbruck'),
(6201 , 'Bregenz'),
(6202 , 'Bregenz'),
(6203 , 'Bregenz')
;WITH Tbl AS
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY Description ORDER BY Id) AS RN,
COUNT(*) OVER(PARTITION BY Description) AS CNT
FROM #tblMasterPropValues
)
, Rcr AS (
SELECT *, CAST(Id AS varchar(max)) Ids
FROM Tbl WHERE RN = 1
UNION ALL
SELECT T.*, Rcr.Ids + ',' + CAST(T.Id AS VARCHAR(10)) Ids
FROM Rcr
INNER JOIN Tbl T ON T.RN = Rcr.RN + 1 and Rcr.Description = T.Description
)
SELECT RN, Description, Ids FROM Rcr
WHERE RN = CNT
Result:
Description Ids
-------------------- -----------------------
Salzburg 6192,6193,6194
Innsbruck 6196,6197,6198,6199
Bregenz 6201,6202,6203
Try this:
DECLARE #Table TABLE(ID INT, Description VARCHAR(25))
INSERT INTO #Table
VALUES (6192,'Salzburg' )
,(6193,'Salzburg' )
,(6194,'Salzburg' )
,(6196,'Innsbruck')
,(6197,'Innsbruck')
,(6198,'Innsbruck')
,(6199,'Innsbruck')
,(6201,'Bregenz' )
,(6202,'Bregenz' )
,(6203,'Bregenz' )
Query:
SELECT DISTINCT T2.Description,
SUBSTRING(
(
SELECT ','+CAST(T1.ID AS VARCHAR) AS [text()]
FROM #Table T1
WHERE T1.Description = T2.Description
ORDER BY T1.Description
FOR XML PATH ('')
), 2, 1000) [Ids]
FROM #Table T2
Result:
Description Ids
Bregenz 6201,6202,6203
Innsbruck 6196,6197,6198,6199
Salzburg 6192,6193,6194

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

Duplicates without using While or Cursor in T-SQL

ID Name
1 A
1 B
1 C
2 X
2 Y
3 P
3 Q
3 R
These are the columns in a table. I want to get output like
ID Company
1 A,B,C
2 X, Y
3 P,Q,R
Restriction is that I cannot use WHILE or CURSOR. Please write a query for the same.
This query should do it - uses FOR XML PATH which is new in SQL Server 2005 - hope you are on 2005 or higher, you didn't clearly specify.....
SELECT
ID,
STUFF(CAST((SELECT ','+Name FROM dbo.YourTable t2
WHERE t2.ID = dbo.YourTable.ID
FOR XML PATH(''), TYPE) AS VARCHAR(MAX)), 1, 1, '') AS 'Company'
FROM
dbo.YourTable
GROUP BY
ID
Here's a solution using the CROSS APPLY method:
select id, sub.names
from (
select distinct id from YourTable
) a
cross apply (
select name + ', ' as [text()]
from YourTable b
where b.id = a.id
for xml path('')
) sub(names)
For 2005 version:
CREATE TABLE dbo.TEST([Type] INTEGER, [Name] NVARCHAR(100), [Qty] INTEGER)
GO
INSERT dbo.TEST VALUES(1, N'a', 5)
INSERT dbo.TEST VALUES(1, N'b', 6)
INSERT dbo.TEST VALUES(2, N'c', 44)
INSERT dbo.TEST VALUES(3, N'd', 1)
GO
select [Type],
[Description] = replace((select [Name] + ':' + cast([Qty] as varchar) as 'data()'
from TEST where [Type] = t.[Type] for xml path('')), ' ', ',')
from dbo.TEST t
group by [Type]
go
drop table dbo.TEST
You can group on the ID to get the unique values, then get the comma separated string for each using a for xml query:
select
a.ID,
substring((
select ', ' + Name
from Test1
where Test1.ID = a.ID
for xml path('')
), 3, 1000) as Company
from
TheTable a
group by
a.ID