SELECT records as comma separated string [duplicate] - sql

This question already has answers here:
Simulating group_concat MySQL function in Microsoft SQL Server 2005?
(12 answers)
Closed 8 years ago.
So I have the following tables:
Table 1
fname mi lname empid
John A Smith 1202
Bob Doe 9815
Table 2
unid empid
1015 1202
1015 9815
Table 3
unid Item
1015 ABC
1015 DEF
My intended output should be (when supplying unid=1015)
fname mi lname item
John A Smith ABC, DEF
Bob Doe
Now that would be the ideal, but I'm more than happy to deal with the repeated [Item] values on the front end.
My current statement is:
select p.FNAME,p.MI,p.LNAME, ac.EQUIP from table1 t1, table2 t2, table3 t3
where t1.EMPID = t2.EMPID and t2.UNID = t3.UNID and t2.unid = '1015' group by t1.FNAME, t1.MI,
t1.LNAME,t3.EQUIP
For the life of me, I cannot figure out how get the values in item (which can be 0 or more to a maximum of 8) as one comma separated string. My problem is, due to site/client constraints, I cannot use an SP but this has to be done in one SQL statement.
This is on SQL SERVER 2008 R2.

Select distinct t.fname,t.mi,t.lname,
STUFF((Select distinct i.item + ','
from Table3 i
where t.unid = tt.unid AND i.unid = '1015'
ORDER BY i.unid
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)')
, 1, 0, ' ') from Table1 t
INNER JOIN Table2 tt
ON tt.empid = t.empid
group by
t.FNAME,
t.MI,
t.LNAME

Related

SQL Query to merge several views into one

I was trying to create a new view out of 3 or 4 other views/tables.
TableA:
title_id
homeTeam
1234
WSV
5678
SSV
7890
NULL
4321
SCC
TableB:
title_id
awayTeam
1234
SSV
5678
SFV
7890
NULL
4321
KFC
TableC:
title_id
homeTeam
1234
SSV
5678
NULL
7890
AAB
4711
BFG
I would like to generate a new view out of those three which looks like:
title_id
Teams
1234
WSV, SSV, SSV
5678
SSV, SFV, N/A
7890
N/A, N/A, AAB
4321
SCC, KFC, N/A
4711
N/A, N/A, BFG
As you can see, NULL should be renamed to N/A, as well if id doesn't exist in one of the other tables. And I would like to get DISTINCT title_id.
#DaleK sure, i tried it like this:
select tableA.title_id, ISNULL(tableA.homeTeam, 'N/A') + ',' +
ISNULL(tableB.awayTeam, 'N/A') + ',' + ISNULL(tableC.homeTeam, 'N/A')
as Teams from tableA, tableB, tableC;
This leads into an neverending query for my tables which has each more than 300k rows.
Next i tried join:
select tableA.title_id, ISNULL(tableA.homeTeam, 'N/A') + ',' +
ISNULL(tableB.awayTeam, 'N/A') + ',' + ISNULL(tableC.homeTeam, 'N/A')
as Teams from tableA FULL JOIN tableB ON tableB.title_id =
tableA.title_id FULL JOIN tableC ON tableC.title_id = tableA.tile_id
But to be honest i wasnt sure about the number of rows.
You can UNION ALL the tables together, then use string aggregation
SELECT
t.title_id,
STRING_AGG(ISNULL(t.team, 'N/A'), ', ') WITHIN GROUP (ORDER BY t.ordering) AS team
FROM (
SELECT
a.title_id,
a.homeTeam AS team,
1 AS ordering
FROM TableA a
UNION ALL
SELECT
b.title_id,
b.awayTeam,
2
FROM TableB b
UNION ALL
SELECT
c.title_id,
c.homeTeam,
3
FROM TableC c
) t
GROUP BY
t.title_id;
For SQL Server 2016 and earlier, you have to use the FOR XML method, and it's less efificent as you have to query the tables multiple times
WITH t AS (
SELECT
a.title_id,
a.homeTeam AS team,
1 AS ordering
FROM TableA a
UNION ALL
SELECT
b.title_id,
b.awayTeam,
2
FROM TableB b
UNION ALL
SELECT
c.title_id,
c.homeTeam,
3
FROM TableC c
)
SELECT
tOuter.title_id,
STUFF(tInner.team.value('text()[1]', 'nvarchar(max)'), 1, LEN(', '), '') AS team
FROM (
SELECT DISTINCT t.title_id
FROM t
) tOuter
CROSS APPLY (
SELECT ', ' + ISNULL(t.team, 'N/A')
FROM t
WHERE t.title_id = tOuter.title_id
ORDER BY t.ordering
FOR XML PATH(''), TYPE
) tInner(team);
db<>fiddle
Try this:
select
COALESCE(a.title_id,b.title_id,c.title_id),
CONCAT(
ISNULL(a.homeTeam,'N/A'),
ISNULL(b.awayTeam,'N/A'),
ISNULL(c.homeTeam,'N/A'),
) 'Teams',
from TableA a
full join TableB b on a.title_id = b.title_id
full join TableC c on c.title_id = a.title_id
where
a.homeTeam is not null
OR b.awayTeam is not null
OR c.homeTeam is not null
group by a.title_id
As for the DISTINCT title_id, it should be unique by default as I assume it is used as the key in each of the tables.

SQL query multiple rows into single row that has JOIN

I am trying to combine multiple rows into a single row that involves a JOIN. I cannot figure how to get the JOIN piece to work.
I am on SQL Server 2014.
This piece works great where I am rolling rows into a single comma separated line based on ID_REVIEW:
SELECT DISTINCT
ID_REVIEW
, STUFF((
SELECT N', ' + CAST(AREA_ID AS VARCHAR(255))
FROM AREA_ASSOC t2
WHERE t1.ID_REVIEW = t2.ID
FOR XML PATH('')
), 1, 1, '') AS AREA_ID
FROM REQUEST_WORKLOAD t1
Result:
ID_REVIEW | AREA_ID
-----------------
11438 | 2
23501 | 10, 15
44677 | 8
What I'd like to do is instead of having numbers for AREA_ID is have the name of that area show up. The goal being to have:
ID_REVIEW | AREA_NM
-----------------
11438 | State St.
23501 | Main St., Second St.
44677 | Adams Ave.
This AREA_NM information is contained in another table, called AREA. In a separate query, I can do a LEFT JOIN on table AREA_ASSOC to pull in the AREA_NM:
SELECT DISTINCT
[AREA_NM]
FROM AREA_ASSOC
LEFT JOIN AREA ON
AREA_ASSOC.AREA_ID = AREA.AREA_ID
I'm stumped as to how to get that JOIN into the STUFF function so I can get the area names. Is there a way to do this?
Do the join in the subquery:
SELECT DISTINCT r2.ID_REVIEW,
STUFF( (SELECT N', ' + a2AREA_NM
FROM AREA_ASSOC aa2 JOIN
AREA a
ON aa2.AREA_ID = A.AREA_ID
WHERE aa2.ID_REVIEW = r2.ID
FOR XML PATH('')
), 1, 2, ''
) AS AREA_ID
FROM REQUEST_WORKLOAD rw

SQL Combine multiple rows into one column and get name from Ids

Consider a database table connectouser holding two IDs:
connectouser
compID coopID
1 1
1 2
1 3
2 1
2 2
Consider another database table coop holding two IDs:
coop
ID Name
1 ABC
2 DEF
3 GHJ
I want to the following output :
Result
compID coopname
1 ABC,DEF,GHJ
2 ABC,DEF
Can anyone please help me on this.
The question was tagged MySQL for this answer.
This is a group by and group_concat():
select cu.compId, group_concat(co.name order by co.id) as coopnames
from connectouser cu join
coop co
on cu.coopID = co.ID
group by cu.compId;
In SQL Server, you can do:
select cu.compId,
stuff( (select ',' + co.name
from coop co
where cu.coopID = co.ID
order by co.id
for xml path ('')
), 1, 1, ''
) as names
from connectouser cu;
The most recent version of SQL Server supports string_agg(), which is a much better approach.

How to combine multiple rows, merging cells with different values across columns and rows using SQL

Below is the form of data I have right now from a SQL query:
ID Name Nationality Institution Degree Result
---------------------------------------------
1 Brian USA a b c
1 Brian USA d e f
1 Brian USA h i j
2 Faye UK y z x
2 Faye UK o p q
And the data would ideally be sorted as below:
ID Name Nationality Background
-------------------------------------------------
1 Brian USA a,b,c; d,e,f; h,i,j
2 Faye UK y,z,x; o,p,q
I'm a SQL beginner and I'd very much appreciate any help with this.
Below is my current SQL query:
select
table1.id,
table1.lastname,
table1.firstname,
table1.group,
table2.institution,
table2.degree,
table2.result,
from
table1
inner join
table2 on (table1.id = table2.id)
where
((table1.startyear = '2017')
and (table1.group = 'A'))
You can query as below:
Select Id, [Name], Nationality,
Background = Stuff((Select '; '+Institution+','+Degree+','+Result from #table1 where id = t.Id for xml path('')),1,2,'')
from #table1 t
Group by Id, [Name], Nationality
So using list() and the || string concat in Firebird ( IBExpert ) gives us:
UNTESTED: List() Doc requires 2.1 version or greater.
A prior SO answer using List()
Note Group is on the reserved words list; so you may have to escape it using " in firebird
SELECT table1.id
, table1.lastname
, table1.firstname
, table1."group"
, List(table2.institution ||','||
table2.degree ||','||
table2.result,';') as Background
FROM table1
INNER JOIN table2
ON table1.id = table2.id
WHERE table1.startyear = '2017'
AND table1."group" = 'A'
GROUP BY table1.id
, table1.lastname
, table1.firstname
, table1."group"

trying to concatenate a column into a comma delimited list

i have 3 tables, 1 for products and one for categories the products are assigned to. what IM trying to do is concatenate the column called stCategoryName to a single column in a comma delimited list.
Basically I have the products table containing the primary key for each product and im trying to figure out how to concatenate all the stcategoryName column next to each product so i can have a simplified return
what im trying to get is the following.
stProductID stCategoryName
123 category1,category2,category3
SELECT
dbo.StoreItemTracking.StCategoryID,
dbo.StoreItemTracking.StProductID,
dbo.StoreItemTracking.viewOrder,
dbo.StoreCategories.StCategoryName,
dbo.Store_Products.PartNumber
FROM
dbo.StoreItemTracking
INNER JOIN dbo.StoreCategories
ON dbo.StoreItemTracking.StCategoryID = dbo.StoreCategories.StCategoryID
INNER JOIN dbo.Store_Products
ON dbo.StoreItemTracking.StProductID = dbo.Store_Products.ID
Im stuck as to how to concatenate a column where the query contains 3 tables to select from.
any help greatly appreciated
Look at using coalesce to turn category into a CSV:
See example:
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '')
+ CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
You can also use CTE's or Subqueries. See:
http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=createacommadelimitedlist
Another nice and easy example:
http://www.codeproject.com/Articles/21082/Concatenate-Field-Values-in-One-String-Using-CTE-i
This:
FId FName
--- ----
2 A
4 B
5 C
6 D
8 E
with:
;WITH ABC (FId, FName) AS
(
SELECT 1, CAST('' AS VARCHAR(8000))
UNION ALL
SELECT B.FId + 1, B.FName + A.FName + ', '
FROM (And the above query will return
SELECT Row_Number() OVER (ORDER BY FId) AS RN, FName FROM tblTest) A
INNER JOIN ABC B ON A.RN = B.FId
)
SELECT TOP 1 FName FROM ABC ORDER BY FId DESC
becomes:
FName
----------------------------
A, B, C, D, E,
Don't understand how your products and categories are connected but in general I do like this to create comma separated lists.
SELECT table1.Id
,Csv
FROM table1
CROSS APPLY (
-- Double select so we can have an alias for the csv column
SELECT (SELECT ',' + table2.Name
FROM table2
WHERE table2.Id = table1.Id
FOR XML PATH('')
) AS RawCsv
) AS CA1
CROSS APPLY (
-- Trim the first comma
SELECT RIGHT(RawCsv, LEN(RawCsv) - 1) AS Csv
) AS CA2