Grouping the results of multiple rows in one column [duplicate] - sql

This question already has answers here:
Can I Comma Delimit Multiple Rows Into One Column? [duplicate]
(5 answers)
Closed 10 years ago.
The query below gives me two results where everything is same except the last column v2_roles.id. Is there a way to group them in one column (may be a comma seprated list) and get just one result back
SELECT v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email,
v2_roles.id
FROM v2_admin
INNER JOIN v2_admin_roles
ON v2_admin.adminid = v2_admin_roles.adminid
INNER JOIN v2_roles
ON v2_admin_roles.roleid = v2_roles.id
WHERE v2_admin.adminid = 2

This should also work,
;WITH mytable AS (
SELECT v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email,
v2_roles.id
FROM v2_admin
INNER JOIN v2_admin_roles
ON v2_admin.adminid = v2_admin_roles.adminid
INNER JOIN v2_roles
ON v2_admin_roles.roleid = v2_roles.id
WHERE v2_admin.adminid = 2
)
SELECT t1.adminid,t1.adminname, t1.login, t1.email,
roleIds =REPLACE( (SELECT convert(varchar,id) AS [data()]
FROM mytable t2
WHERE t2.adminid = t1.adminid
--ORDER BY t2.adminid
FOR XML PATH('')
), ' ', ' , ')
FROM mytable t1
GROUP BY t1.adminid,t1.adminname, t1.login, t1.email ;

This is a little trick using FOR XML to convert the field to a list and STUFF to remove the beginning comma -- this should be close (untested):
SELECT v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email,
STUFF(
(
SELECT ',' + CAST(v2_roles.id as varchar) AS [text()]
FROM v2_roles
WHERE v2_admin_roles.roleid = v2_roles.id
ORDER BY v2_roles.id
FOR XML PATH('')
), 1, 1, '') AS Roles
FROM v2_admin
INNER JOIN v2_admin_roles
ON v2_admin.adminid = v2_admin_roles.adminid
WHERE v2_admin.adminid = 2
GROUP BY v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email

Related

String_agg equivalent function in SQL server [duplicate]

This question already has answers here:
String_agg for SQL Server before 2017
(2 answers)
Closed 2 years ago.
I want to rewrite my SQL query with stuff or other option available instead of string_agg function as my SQL server doesn't support it.
Can anyone please help me with this?
select String_agg(air.code,',') AS Code,String_agg(air.Id,',') AS AId,res.ResId
from Table1 air
inner join
Table2 rmap on air.Id=airmap.Id
inner join Table3 res on rmap.ResId=res.ResId
group by res.ResId
with output like below
Presumably, you want something like this:
select res.ResId,
stuff( (select ',' + air.code
from table1 air inner join
Table2 rmap
on air.Id = airmap.Id
where rmap.ResId = res.ResId
for xml path ('')
), 1, 1, '') as codes,
stuff( (select ',' + air.aid
from table1 air inner join
Table2 rmap
on air.Id = airmap.Id
where rmap.ResId = res.ResId
for xml path ('')
), 1, 1, '') as aids
from Table3 res ;

SQL Server : passing company id (int) with comma in where condition [duplicate]

This question already has answers here:
How to split a comma-separated value to columns
(38 answers)
Closed 4 years ago.
I am working in SQL Server 2008. I am facing a problem in a where condition, passing multiple company ID values separated by comma (,) to use in Int company ID.
ALTER Procedure
[dbo].[SP_WorkOrderDetails] #CompanyID varchar(50)
as begin
Select
*
from
ClientContract C
left join
WorkOrder W
on
C.Id=W.ClientContractId
left join
ClientContractContacts CB
on
CB.ClientContractld=C.Id
left join
Client CL
on
CL.Id= C.Clientld
left join
Client CN
on
CN.Id= CB.Contactld
left join
BaseUnit B
on
B.Id=W.BaseUnitId
left join
users u
on
u.Staffld = W.AssignedTo
left join
LatticeERP_DFS..sv_App_Staff SPT
on
SPT.Leaderld=W.AssignedTo and
SPT.Module = 'S'
left join
Staff SS
on
SS.Id=u.StaffId --and ss.IsTeamLeader = 1
left join
Companies Comp
on
Comp.id=C.Companyld
Where
convert(nvarchar(50),isnull(C.companyID, 1)) in (replace('1,7', '''', ','))
Order By
ContractCode,
WorkOrderNo Desc
end
can you try this
IN (select cast ( STRING_SPLIT ( '1,7' , ',' ) as int ) )
or may be this
IN ( SELECT
Split.a.value('.', 'VARCHAR(100)') AS CVS
FROM
(
SELECT CAST ('<M>' + REPLACE('1,7', ',', '</M><M>') + '</M>' AS XML) AS CVS
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a) )
you can use this table-valued function:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
create FUNCTION dbo.SplitString(#str VARCHAR(4000),#seprator VARCHAR(1))
RETURNS TABLE
AS
RETURN ( WITH tokens(p,a,b) AS (SELECT 1,1,CHARINDEX(#seprator,#str)
UNION ALL SELECT p+1,b+1,CHARINDEX(#seprator,#str,b+1)
FROM tokens WHERE b>0
)
SELECT
SUBSTRING(#str,a,CASE WHEN b > 0 THEN b-a ELSE 4000 end)
AS VALUE
FROM tokens)
GO
use it like:
... where ID In(select value from dbo.SplitString('1,7,...',','))

How to get values other from a string in SQL

I'm using the stuff function to get a list of ids. But there are some values that are duplicate:
----------
3180,3181,3182,3180,4180
----------
3183,3184,3184,4181
I just want to get the list of ids that are not duplicated, desired results:
----------
3181,3182,4180
----------
3183,4181
This my query:
SELECT oa.AssetId,
oal.AssetLineId,
SNIds = STUFF((SELECT ', ' + CAST(isn1.Id AS VARCHAR(MAX))
FROM dbo.InventoryOperation o1
INNER JOIN dbo.InventoryOperationAsset oa1 ON oa1.OperationId = o1.OperationId
INNER JOIN dbo.InventoryOperationAssetLine oal1 ON oal1.OperationAssetId = oa1.OperationAssetId
INNER JOIN dbo.InventoryOperationAssetLineSerialNumber ioalsn1 ON ioalsn1.OperationAssetLineId = oal1.OperationAssetLineId
INNER JOIN dbo.InventorySerialNumber isn1 ON isn1.Id = ioalsn1.SerialId
WHERE oa.AssetId = oa1.AssetId AND oal.AssetLineId = oal1.AssetLineId
FOR XML PATH('')),1,2,'')
FROM dbo.InventoryOperation o
INNER JOIN dbo.InventoryOperationAsset oa ON oa.OperationId = o.OperationId
INNER JOIN dbo.InventoryOperationAssetLine oal ON oal.OperationAssetId = oa.OperationAssetId
INNER JOIN dbo.InventoryOperationAssetLineSerialNumber ioalsn ON ioalsn.OperationAssetLineId = oal.OperationAssetLineId
GROUP BY oa.AssetId, oal.AssetLineId;
Can anyone help me with this issue? Thanks in advance if anyone could help.
You could use
SELECT DISTINCT columns FROM table;
That makes sure you only get non duplicates.
Query that provides data to STUFF function should use following query to get only unique ids (e.g. 3181,3182,4180,3183,4181) and not the ones that have duplicates (e.g. 3180,3184)
SELECT column_name
FROM TABLE_NAME
GROUP BY column_name
HAVING COUNT(*) = 1;
Updating answer with STUFF function sample ...
SELECT STUFF(', ' + REPLACE((SELECT id + ', ' AS 'data()'
FROM stackoverflow
GROUP BY id
HAVING COUNT(*) = 1
FOR XML PATH('')), '', ''), 1, 2, '')
Sample Run

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

How to combine values in SQL stored procedure

I have a stored procedure
SELECT P.Name,P.Description,
PP.Attribute,PD.Value
FROM admin.Profiles P
LEFT JOIN admin.ProfilePreferenceMap PPM on P.ProfileID=PPM.ProfileID
LEFT JOIN admin.ProfilePrefDtl PD on PD.ProfilePrefDtlID=PPM.PreferenceID
LEFT JOIN admin.ProfilePref PP on PP.ProfilePrefID=PD.ProfilePrefID
WHERE P.Name='Profile1'
which returns the rows like
Name Description Attribute Value
Profile1 Profile 1 description E EV
Profile1 Profile 1 description S SV
I would like to get the result as
Name Description Attribute Value
Profile1 Profile 1 description E,S EV,SV
My purpose is to convert this values to JSON data like -
[{"Name":"Profile1","Description":"Profile 1 description","Attribute":["E", "S"],"Value":["EV", "SV"]}]
You should emulate GROUP_CONCAT() which exists in MySql
SQLFiddle demo
with t as
(
SELECT P.Name,P.Description,
PP.Attribute,PD.Value
FROM admin.Profiles P
LEFT JOIN admin.ProfilePreferenceMap PPM on P.ProfileID=PPM.ProfileID
LEFT JOIN admin.ProfilePrefDtl PD on PD.ProfilePrefDtlID=PPM.PreferenceID
LEFT JOIN admin.ProfilePref PP on PP.ProfilePrefID=PD.ProfilePrefID
WHERE P.Name='Profile1'
)
select
Name,Description,
stuff((select ', ' + Attribute
from t t2 where t1.NAme = t2.NAme and t1.Description = t2.Description
for xml path('')),
1,2,'') [Attributes],
stuff((select ', ' + Value
from t t2 where t1.NAme = t2.NAme and t1.Description = t2.Description
for xml path('')),
1,2,'') [Values]
from t t1
group by Name,Description
You could use group by to group by unique name or description column but i'm not sure there is a easy way to get the comma separated value, made of values across separate rows, unless you did something with Temp tables and CONCAT() possibly?
If grouping is ok try this:
SELECT P.Name,P.Description,
PP.Attribute,PD.Value
FROM admin.Profiles P
LEFT JOIN admin.ProfilePreferenceMap PPM on P.ProfileID=PPM.ProfileID
LEFT JOIN admin.ProfilePrefDtl PD on PD.ProfilePrefDtlID=PPM.PreferenceID
LEFT JOIN admin.ProfilePref PP on PP.ProfilePrefID=PD.ProfilePrefID
WHERE P.Name='Profile1'
GROUP BY P.Name
However, grouping like this will only show the first row (based on sort) of your Attribute and Value columns howe