Create comma separated group list from rows - sql

I need to extract a comma separated list from the following:
Return should gives something like
1 : Route#1, Route#2
2 : Route#3, Route#4
3 : Route#5
4 : Route#6
I'm struggling with the STUFF function. So far I have:SELECT STUFF( (SELECT DISTINCT ';' + T4.[Outbound Trucks] FROM #TEMP4 T4 FOR XML PATH('') ),1,1,'') AS MasterRoutes
Result gives me
any help would be really appreciated.
thanks a lof for your time

If your sql server is 2017 or more :
SELECT dorno, STRING_AGG ([Outbound Trucks], ',') as CSV
FROM #TEMP4
GROUP BY dorno
Explanation Here
In you case you can eliminate doublon to like this:
with tmp as (
select distinct dorno, [Outbound Trucks] Truck from #TEMP4
)
SELECT dorno, STRING_AGG (Truck, ',') as CSV
FROM tmp
GROUP BY dorno

Related

Concatenate strings from multiple columns and multiple rows

How to concatenate the strings from multiple rows and multiple columns in SQL Server.
My table is like this:
ItemId AttributeName AttributeValue
---------- ------------- --------------
1 Website www.abc.com
1 Github github.com/abc
1 Facebook facebook.com/abc
2 Website www.123.com
2 Instagram instagram.com/123
and the desired output is:
ItemId Weblinks
---------- -------------
1 Website: www.abc.com; Github: github.com/abc; Facebook: facebook.com/abc
2 Website: www.123.com; Instagram: instagram.com/123
I read from other similar questions that XML PATH is probably required. Please could anyone guide me how to achieve this?
This can also be done with a 2 step query:
SELECT t.id, STRING_AGG(t.sites, ' ') as Weblinks
FROM (
SELECT id, CONCAT(attrName, ': ', attrValue, ';') as sites
FROM test
) as t
GROUP BY t.id
ORDER BY t.id;
The inner concatenates attribute value and name in the desired format, while the outer aggregates the results per user id. Coming from MySQL I find that simpler for some reason.
Demo: here
UPDATE: based on #Panagiotis comment
SELECT t.id, STRING_AGG(CONCAT(t.attrName, ': ', t.attrValue, ';'), ' ') as Weblinks
FROM test t
GROUP BY t.id
ORDER BY t.id;
Demo 2: here
You can use FOR XML PATH() :
SELECT DISTINCT T.ItemId, STUFF(Weblinks, 1, 1, '') AS Weblinks
FROM table T CROSS APPLY
( SELECT CONCAT(';', T1.AttributeName, ':', T1.AttributeValue)
FROM table T1
WHERE T1.ITEMID = T.ITEMID
FOR XML PATH('')
) T1(Weblinks);

How to combine return results of query in one row

I have a table that save personnel code.
When I select from this table I get 3 rows result such as:
2129,3394,3508,3534
2129,3508
4056
I want when create select result combine in one row such as:
2129,3394,3508,3534,2129,3508,4056
or distinct value such as:
2129,3394,3508,3534,4056
You should ideally avoid storing CSV data at all in your tables. That being said, for your first result set we can try using STRING_AGG:
SELECT STRING_AGG(col, ',') AS output
FROM yourTable;
Your second requirement is more tricky, and we can try going through a table to remove duplicates:
WITH cte AS (
SELECT DISTINCT VALUE AS col
FROM yourTable t
CROSS APPLY STRING_SPLIT(t.col, ',')
)
SELECT STRING_AGG(col, ',') WITHIN GROUP (ORDER BY CAST(col AS INT)) AS output
FROM cte;
Demo
I solved this by using STUFF and FOR XML PATH:
SELECT
STUFF((SELECT ',' + US.remain_uncompleted
FROM Table_request US
WHERE exclusive = 0 AND reqact = 1 AND reqend = 0
FOR XML PATH('')), 1, 1, '')
Thank you Tim

Find "LIKE" duplicates in MSSQL

I got a MSSQL database and there's this column with IDs.
Some are {}-wrapped around the ID and some are not.
I need to find out if there are duplicate entries like:
'{abcd}' and 'abcd' in one column.
Obviously I dont know 'abcd'...
Is there a simple way of joining the same column and searching for "LIKE" duplicates? Inner Join is not working for me...
You could do something like this:
SELECT Id
FROM TableName AS T0
WHERE EXISTS
(
SELECT 1
FROM TableName AS T1
WHERE T0.Id = '{' + T1.Id + '}'
-- Uncomment the next row if you want all duplicates (with or without brackets):
-- OR '{' + T0.Id + '}' = T1.Id
)
This will return all the records where the id is wrapped by curly brackets and has duplicate id just without the brackets.
You can also do like
CREATE TABLE T(
ID VARCHAR(25)
);
INSERT INTO T VALUES
('abc'),
('{abc}'),
('def'),
('ghi'),
('{ghi}');
SELECT *
FROM
(
SELECT TRIM(TRANSLATE(ID, '{}', ' ')) ID
FROM T
) TT
GROUP BY ID
HAVING COUNT(ID) > 1;
-- Or you can also do
SELECT *
FROM
(
SELECT REPLACE(REPLACE(ID, '{', ''), '}', '') ID
FROM T
) TT
GROUP BY ID
HAVING COUNT(ID) > 1;
Note that TRANSLATE() and TRIM() functions is available only in SQL Server 2017

Inner query comma separated results

My Query is:
SELECT project_type_name FROM project_type WHERE project_type_id IN
(SELECT project_type_id FROM projects WHERE project_id = 93)
Where inner query returns 1 row with 3 comma separated values. (2,3,4). But outer query returns only 1 record only for 2.
You should use find_in_set for this purpose.
SELECT project_type_name
FROM project_type
WHERE FIND_IN_SET( project_type_id, (
SELECT project_type_id
FROM projects
WHERE project_id =93
) )
You cannot treat a string of comma separated values like a list of values. In case the subquery returns always one row you can use LIKE:
SELECT project_type_name
FROM project_type
WHERE CONCAT(',', (SELECT project_type_id FROM projects WHERE project_id = 93), ',')
LIKE '%,' + project_type_id ',%'

Reshape SQL date

following problem
I am using the command to join Names with project numbers
SELECT DDR_namen.vorname_nachname, DDR_Erfinder_final.pubnr
FROM DDR_namen
RIGHT JOIN DDR_Erfinder_final
ON DDR_namen.vorname_nachname=DDR_Erfinder_final.vorname_nachname
which gives me someting like this (small example)
vorname_nachname Pubnr (ID)
A. Heinrich 100
B. Müller 100
B. Müller 101
B. Müller 105
C. Krüger 120
C. Krüger 100
Now I want to reshape the data, so that the rows are unique and the ID are combined into a new collumn. Like this.
vorname_nachname Pubnr (ID)
A. Heinrich 100
B. Müller 100;101;105
C. Krüger 120;100
Anybody and ideas?
Try grouping like
select vorname_nachname,
(
SELECT STUFF((SELECT ';' + CAST(Pubnr AS VARCHAR(MAX))
FROM TestTable
WHERE vorname_nachname = t1.vorname_nachname
FOR XML PATH('') ), 1, 1, '')
) AS Pubnr
from TestTable t1
group by vorname_nachname
SQL Fiddle Demo : http://sqlfiddle.com/#!3/d0916/1
UPDATE : For JOIN you can use CTE like below :
;WITH CTE AS
(
SELECT DDR_namen.vorname_nachname, DDR_Erfinder_final.pubnr
FROM DDR_namen
RIGHT JOIN DDR_Erfinder_final
ON DDR_namen.vorname_nachname=DDR_Erfinder_final.vorname_nachname
)
select vorname_nachname,
(
SELECT STUFF((SELECT ';' + CAST(Pubnr AS VARCHAR(MAX))
FROM CTE
WHERE vorname_nachname = t1.vorname_nachname
FOR XML PATH('') ), 1, 1, '')
) AS Pubnr
from CTE t1
group by vorname_nachname