SQL query with comma separated values - sql

I have a requirement wherein I have 3 tables
ContactInfo
idContactinfo FirstName Lastname idCOmpanyid
---------------------------------------------------
1 Blah1 Blah1 1
2 Blah2 Blah2 1
3 Blah3 Blah3 1
4 Blah4 Blah4 1
ContactRole
idcontactrole IdContactRoleName idContactInfo
------------------------------------------------------
1 1 1
2 1 2
3 1 3
4 2 4
IdContactRoleLookup
idcontactRole RoleName
----------------------------------
1 Admin
2 Secretary
I need a query that gives me a result like this
idcontactrolename Contacts
--------------------------------------------------------
Admin Blah1,Blah1;Blah2,Blah2,Blah3,Blah3
Secretary Blah4,Blah4
This is what I have till now !!
SELECT l.sValue
, SUBSTRING((
SELECT C.sLast + ',' + C.sFirst + ';'
FROM contactinfo c
inner join contactrole crole
ON crole.idcontactinfo = c.idcontactinfo
WHERE crole.idcompany = '<<blah>>'
and c.idcompany = '<<blah>>'
FOR XML PATH('')
), 1, 1000000)
FROM CONTACTROLE CR
inner join contactinfo c on
cr.idcontactinfo = c.idcontactinfo
inner join lookupdata l on cr.idlookuprole = l.idlookupdata
where c.idcompany = '<<blah>>'

SELECT
RoleName,
STUFF(
(
SELECT ';' + b.FirstName + ', ' + b.LastName
FROM ContactRole a
INNER JOIN ContactInfo b
ON a.idContactInfo = b.idContactinfo
WHERE a.IdContactRoleName = r.idcontactRole
FOR XML PATH (''))
, 1, 1, '') AS NamesList
FROM IdContactRoleLookup r
GROUP BY idcontactRole, RoleName
SQLFiddle Demo

I Would do somethng like this, where you use the ID of the main QUERY into your SUBQUERY
SELECT
l.sValue
, SUBSTRING((
SELECT C.sLast + ',' + C.sFirst + ';'
FROM contactinfo c
inner join contactrole crole
ON crole.idcontactinfo = c.idcontactinfo
WHERE c.idcompany = '<<blah>>'
AND c.idcontactrole = CR.idcontactrole
FOR XML PATH('')
), 1, 1000000)
FROM CONTACTROLE CR
inner join lookupdata l on cr.idlookuprole = l.idlookupdata
This will give you all the role for one Compagnie. If the role does'nt exist you will have a NULL value.

You can use CROSS APPLY to get the result:
select distinct l.RoleName,
left(list, len(list) -1) list
FROM CONTACTROLE CR
inner join IdContactRoleLookup l
on cr.IdContactRoleName = l.idcontactRole
cross apply
(
select C1.Lastname + ',' + C1.FirstName + ';'
from CONTACTROLE CR1
inner join contactinfo c1
on cr1.idContactInfo = c1.idContactinfo
where cr.IdContactRoleName = cr1.IdContactRoleName
FOR XML PATH('')
) t2 (list)
See SQL Fiddle with Demo

Related

Update a column separated by comma for multiple values?

I have following table Userinfo_attarea:
id employee_id area_id
182521 4391 2
182522 4391 3
Personnel_area:
id areaid
1 Area Name
2 PROJECT80
3 PROJECT69
When i update it works fine foe single value but i need a column with multiple values separeted by comma as mentioned below
Expected Output:
areaname
PROJECT80,PROJECT69
i am using following query for update
UPDATE employee
SET employee.areaname = p.areaname
FROM employee join userinfo u
on u.badgenumber=employee.emp_reader_id join userinfo_attarea ua on ua.employee_id=u.userid join personnel_area p on ua.area_id=p.id
JOIN inserted I ON u.userid= I.employee_id
Thanks in advance...
You can try this :
Update E set areaname = T.areaname from #Employee E
Inner Join
(
Select employee_id,STUFF((SELECT ', ' + CAST(areaid AS VARCHAR(10)) [text()]
FROM (
Select U.employee_id,P.areaid from #Userinfo_attarea U
Inner Join #Personnel_area P on U.area_id = P.id
) B
WHERE employee_id = A.employee_id
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') areaname from
(
Select U.employee_id,P.areaid from #Userinfo_attarea U
Inner Join #Personnel_area P on U.area_id = P.id
) A
GROUP BY employee_id
) T on T.employee_id = E.id
Working demo

SQL Moving SUBSTRING select into INNER JOIN

I have this query
SELECT ID,
SUBSTRING(( SELECT DISTINCT ',' + CONVERT(varchar(10), CC.CompanyId)
FROM Company CC
INNER JOIN CompanyProducts NP2
ON CC.CompanyId = NP2.CompanyId
WHERE NP.CompanyProducts Id = NP2.PrimaryCompanyProducts Id
AND NP2.CompanyProducts Id <> NP2.CompanyProducts Id
FOR XML PATH('')),2,200000) AS CompanyIdList
FROM CompanyProducts NP
I would like to add the SELECT into an INNER JOIN which I will add to my select to check if the return is null or zero
it will be something like this
SELECT ID,
SUBSTRING(( SELECT DISTINCT ',' + CONVERT(varchar(10), CC.CompanyId)
FROM Company CC
INNER JOIN CompanyProducts NP2
ON CC.CompanyId = NP2.CompanyId
WHERE NP.CompanyProducts Id = NP2.PrimaryCompanyProducts Id
AND NP2.CompanyProducts Id <> NP2.CompanyProducts Id
FOR XML PATH('')),2,200000) AS CompanyIdList,
CompanyIdCount --this will be null or a real value
FROM cmp.CompanyProducts NP
INNER JOIN(SELECT DISTINCT A.CompanyProductsId,
(SELECT DISTINCT ',' + CONVERT(varchar(10), CC.CompanyId)
FROM Company CC
INNER JOIN CompanyProducts NP2
ON CC.CompanyId = NP2.CompanyId
WHERE NP.CompanyProducts Id = NP2.PrimaryCompanyProducts Id
AND NP2.CompanyProducts Id <> NP2.CompanyProducts Id ) AS CompanyIdCount
FROM cmp.CompanyProducts A
)E ON NP.CompanyNotificationId = E.CompanyNotificationId
How can I get the inner JOIN to incident null for no records or 1 record or more? THanks

Select With Union In SQL

Why when i run the syntax in sql and the result will be double data?
The command is :
SELECT 1 AS Urut, M.Kode_Project, M.Nama_Project, M.Kode_Panel, D .Nama_Stater1, D .Tipe, D .Komponen, D .Pole, D .Amps, D .Merek, D .Qty, D .IsTitipan
FROM TransM M INNER JOIN
TransD D ON M.Kode_Project = D .Kode_Project AND M.Kode_Panel = D .Kode_Panel
WHERE M.Kode_Project = '17-0002' AND M.Kode_Panel = 'A'
UNION ALL
SELECT 2 AS Urut, M.Kode_Project, M.Nama_Project, M.Kode_Panel, M.Nama_Stater1, 'COOPER (' + SubString(Kode, 5, 100) + ')' AS Tipe,
' (' + LT + ') X ' + CONVERT(VarChar(20), Lapis) AS Komponen, '' AS Pole, '' AS Amps, ' IMPORT ' AS Merek, 1 AS Qty, 0 AS IsTitipan
FROM TransM M INNER JOIN
TransW W ON M.Kode_Project = W.Kode_Project AND M.Kode_Panel = W.Kode_Panel
WHERE LEFT(Kode, 1) <= 'B' AND M.Kode_Project = '17-0002' AND M.Kode_Panel = 'A'
What's the wrong in the command?, Thank's for who's helping.
UNION ALL will merge duplicate rows from result of two select, change
UNION ALL
to just
UNION
this will remove duplicate rows from the result

Convert a column of Rows to only one column column in SQL Server query

I have this query in SQL Server 2012 :
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
The result is like this :
id productid
1 1
1 2
1 3
1 10
2 5
2 1
3 4
3 11
but I want this result :
1 1,2,3,10
2 5,1
3 4,11
How can I get that result ?
Try this:
WITH cte as
(
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
)
SELECT id, productid =
STUFF((SELECT ', ' + productid
FROM cte b
WHERE b.id= a.id
FOR XML PATH('')), 1, 2, '')
FROM cte a
GROUP BY id
Use the below query for the desired output.
SELECT tblplantitle.id
, STUFF((SELECT ', ' + CAST(tblplantoproductpayment.productid AS VARCHAR(10)) [text()]
FROM tblplantoproductpayment
WHERE tblplantoproductpayment.planid = tblplan.id
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' ') List_ProductIds
FROM tblplantitle
INNER JOIN tblplan on tblplan.plantitleid = tblplantitle.id
GROUP BY tblplantitle.id

Query for comma-separated ids to comma-separated values

I have 2 tables
Departments
ID Dept
---------
1 HR
2 Accts
3 IT
Employee
ID Name Depts
-------------------
1 Kevin 2,1
2 Michelle 1
3 Troy 1,3
4 Rheesa 2,3,1
I am looking for an output like the following with a SQL query.
Employee depts
ID Name Depts
-------------------------
1 Kevin Accts,HR
2 Michelle HR
3 Troy HR,IT
4 Rheesa Accts,IT,HR
I have tried the following that join s with depts but results in one row for each dept only. How do i get the above results using a query?
select
name, depts, dept
from
employee
CROSS APPLY
dbo.split_list(employee.depts ,',') split
inner join
dbo.department on depts= split.value
order by
name
DECLARE #Departments TABLE
(
ID INT PRIMARY KEY,
Dept VARCHAR(32) NOT NULL UNIQUE
);
DECLARE #Employees TABLE
(
ID INT PRIMARY KEY,
Name NVARCHAR(64) NOT NULL,
Depts VARCHAR(255) NOT NULL
);
INSERT #Departments VALUES
(1,'HR'), (2,'Accts'), (3,'IT');
INSERT #Employees VALUES
(1,'Kevin','2,1'), (2,'Michelle','1'),
(3,'Troy','1,3'), (4,'Rheesa','2,3,1');
SELECT ID, Name, Depts = STUFF((SELECT ',' + d.Dept
FROM #Departments AS d
INNER JOIN #Employees AS ei
ON ',' + ei.Depts + ',' LIKE '%,' + CONVERT(VARCHAR(12), d.id) + ',%'
WHERE ei.ID = e.ID
ORDER BY Dept
FOR XML PATH,
TYPE).value(N'/text().[1]', N'nvarchar(max)'), 1, 1, N'')
FROM #Employees AS e
ORDER BY ID;
The results don't quite match your required results, as the ordering is deterministic (ordered by department name):
ID Name Depts
---- -------- ----
1 Kevin Accts,HR
2 Michelle HR
3 Troy HR,IT
4 Rheesa Accts,HR,IT
If you want them ordered by the appearance in the comma-separated list, just change:
ORDER BY Dept
To:
ORDER BY CHARINDEX( ',' + CONVERT(VARCHAR(12), d.id) + ',', ',' + ei.Depts + ',')
Results:
ID Name Depts
---- -------- ----
1 Kevin Accts,HR
2 Michelle HR
3 Troy HR,IT
4 Rheesa Accts,IT,HR -- this is the only one affected as it turns out
However, in reality, you should normalize your database. This is an absolute nightmare.
Looking beyond how you're storing your data, let me try to help you out.
Well, you're asking a lot of questions here. First, to split the data, you can format it as XML and use CROSS APPLY -- trick I saw a while back that didn't require built in functions.
That will convert your comma delimited string to a list of strings. You can then use FOR XML to put them back together.
Give this a shot:
SELECT
E.Id,
E.Name,
STUFF(
(
SELECT ',' + D.Department AS [text()]
FROM (
SELECT A.[id],
Split.a.value('.', 'VARCHAR(100)') AS DeptId
FROM
(SELECT [id],
CAST ('<M>' + REPLACE(Depts, ',', '</M><M>') + '</M>' AS XML) AS String
FROM Employee
) AS A
CROSS APPLY String.nodes ('/M') AS Split(a)) A
JOIN Departments D ON A.DeptId = D.Id
WHERE E.Id = A.Id
FOR XML PATH('')
), 1, 1, '') AS Departments
FROM Employee E
And here is the SQL Fiddle.
Good luck.
You can also use a recursive CTE to split the data and then use FOR XML PATH to concatenate the rows into a single row:
;with cte (id, name, deptid, depts) as
(
select id, name,
cast(left(depts, charindex(',',depts+',')-1) as varchar(50)) deptid,
stuff(depts, 1, charindex(',',depts+','), '') depts
from employee
union all
select id, name,
cast(left(depts, charindex(',',depts+',')-1) as varchar(50)) deptid,
stuff(depts, 1, charindex(',',depts+','), '') depts
from cte
where depts > ''
)
select e.id, e.name,
stuff((
select distinct ', '+ d.dept
from cte c
inner join departments d
on c.deptid = d.id
where e.id = c.id
for XML path('')),1,1,'') Depts
from employee e
See SQL Fiddle with Demo
Result:
| ID | NAME | DEPTS |
----------------------------------
| 1 | Kevin | Accts, HR |
| 2 | Michelle | HR |
| 3 | Troy | HR, IT |
| 4 | Rheesa | Accts, HR, IT |
Also you can use option with dynamic management function sys.dm_fts_parser
Before script execution you need check full-text component is installed:
SELECT FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled')
0 = Full-text is not installed.
1 = Full-text is installed.
NULL = Invalid input, or error.
If 0 = Full-text is not installed then this post is necessary to you How to install fulltext on sql server 2008?
SELECT b.ID, b.Name, STUFF((
SELECT ',' + d.Dept
FROM Employees e
JOIN Departments d ON d.ID IN(
SELECT display_term
FROM sys.dm_fts_parser('"' + e.Depts + '"', 1033, NULL, 0)
WHERE display_term NOT LIKE 'nn%'
)
WHERE b.ID = e.ID
ORDER BY d.Dept
FOR XML PATH('')), 1, 1, '') AS Depts
FROM Employees b
OR
SELECT e.ID, e.Name,
(
STUFF((
SELECT ',' + Dept
FROM sys.dm_fts_parser('"' + e.Depts + '"', 1033, NULL, 0) p JOIN Departments d ON p.display_term = d.ID
WHERE display_term NOT LIKE 'nn%'
FOR XML PATH('')), 1, 1, '')
) AS Depts
FROM Employees e
Write a function for splitting comma separated values. I wrote dbo.split
select * from dbo.split('1,2,3',',')
Will return as -
Data
1
2
3
SELECT tact.ActivityID,CONVERT(NVARCHAR(20),tact.createddate,103) AS CallDate,
ActivityOriginatedByPartyID , (ISNULL(p.firstname,'')+' '+ISNULL(p.lastname,'')) AS PartnerName,
u.UserName AS PSTName, ccv.codevalue AS CallType
**, ccv1.codevalue AS CallContext**
,tact.ActivityNote AS CallTrackerNote,
(CONVERT(VARCHAR(20),tact.ActivityTimeSpend) + ' Min') AS CallDuration
FROM txn_activity tact (NOLOCK)
INNER JOIN TXN_Party p (NOLOCK) ON p.PartyID = tact.ActivityOriginatedByPartyID
INNER JOIN TXN_User u (NOLOCK) ON u.userid = tact.createdby
INNER JOIN CFG_CodeValue ccv (NOLOCK) ON ccv.codevalueid = tact.ActivityTypeID
--INNER JOIN CFG_CodeValue ccv1 (NOLOCK) ON ccv1.codevalueid = tact.ActivityContext
**CROSS APPLY
dbo.split(tact.ActivityContext,',') split
inner join
dbo.CFG_CodeValue ccv1 (NOLOCK) ON ccv1.codevalueid = split.data**