How to combine values in SQL stored procedure - sql

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

Related

Use Data of 1 table into another one dynamically

I have one table category_code having data like
SELECT Item, Code, Prefix from category_codes
Item Code Prefix
Bangles BL BL
Chains CH CH
Ear rings ER ER
Sets Set ST
Rings RING RG
Yellow GOld YG YG........
I have another table item_categories having data like
select code,name from item_categories
code name
AQ.TM.PN AQ.TM.PN
BL.YG.CH.ME.PN BL.YG.CH.ME.PN
BS.CZ.ST.YG.PN BS.CZ.ST.YG.PN
CR.YG CR.YG.......
i want to update item_categories.name column corresponding to category_code.item column like
code name
BL.YG.CH.ME.PN Bangles.Yellow Gold.Chains.. . . .
Please suggest good solution for that. Thanks in advance.
First, split the code into several rows, join with the category code and then, concat the result to update the table.
Here an example, based on the data you gave
create table #category_code (item varchar(max), code varchar(max), prefix varchar(max));
create table #item_categories (code varchar(max), name varchar(max));
insert into #category_code (item, code, prefix) values ('Bangles','BL','BL'),('Chains','CH','CH'),('Ear rings','ER','ER'), ('Sets','Set','ST'),('Rings','RING','RG'), ('Yellow gold','YG','YG');
insert into #item_categories (code, name) values ('AQ.TM,PN','AQ.TM.PN'),('BL.YG.CH.ME.PN','BL.YG.CH.ME.PN'),('BS.CZ.ST.YG.PN','BS.CZ.ST.YG.PN')
;with splitted as ( -- split the codes into individual code
select row_number() over (partition by ic.code order by ic.code) as id, ic.code, x.value, cc.item
from #item_categories ic
outer apply string_split(ic.code, '.') x -- SQL Server 2016+, otherwise, use another method to split the data
left join #category_code cc on cc.code = x.value -- some values are missing in you example, but can use an inner join
)
, joined as ( -- then joined them to concat the name
select id, convert(varchar(max),code) as code, convert(varchar(max),coalesce(item + ',','')) as Item
from splitted
where id = 1
union all
select s.id, convert(varchar(max), s.code), convert(varchar(max), j.item + coalesce(s.item + ',',''))
from splitted s
inner join joined j on j.id = s.id - 1 and j.code = s.code
)
update #item_categories
set name = substring (j.item ,1,case when len(j.item) > 1 then len(j.item)-1 else 0 end)
output deleted.name, inserted.name
from #item_categories i
inner join joined j on j.code = i.code
inner join (select code, max(id)maxid from joined group by code) mj on mj.code = j.code and mj.maxid = j.id

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

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

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

Consolidating results on one row SQL

I would like to consolidate a one to many relationship that outputs on different rows to a single row.
(select rate_value1
FROM xgenca_enquiry_event
INNER JOIN xgenca_enquiry_iso_code_translation
ON
xgenca_enquiry_event_rate.rate_code_id
= xgenca_enquiry_iso_code_translation.id
where xgenca_enquiry_event_rate.event_id = xgenca_enquiry_event.id
and ISO_code = 'PDIV') as PDIVrate,
(select rate_value1
FROM xgenca_enquiry_event
INNER JOIN xgenca_enquiry_iso_code_translation
ON
xgenca_enquiry_event_rate.rate_code_id
= xgenca_enquiry_iso_code_translation.id
where xgenca_enquiry_event_rate.event_id = xgenca_enquiry_event.id
and ISO_code = 'TAXR') as TAXrate
PDIVrate TAXrate
NULL 10.0000000
0.0059120 NULL
I would like the results on one row. Any help would be greatly appreciated.
Thanks.
You can use an aggregate function to perform this:
select
max(case when ISO_code = 'PDIV' then rate_value1 end) PDIVRate,
max(case when ISO_code = 'TAXR' then rate_value1 end) TAXRate
FROM xgenca_enquiry_event_rate r
INNER JOIN xgenca_enquiry_iso_code_translation t
ON r.rate_code_id = t.id
INNER JOIN xgenca_enquiry_event e
ON r.event_id = e.id
It looks like you are joining three tables are are identical in the queries. This consolidates this into a single query using joins.
Look here:
Can I Comma Delimit Multiple Rows Into One Column?
Simulate Oracle's LISTAGG() in SQL Server using STUFF:
SELECT Column1,
stuff((
SELECT ', ' + Column2
FROM tableName as t1
where t1.Column1 = t2.Column1
FOR XML PATH('')
), 1, 2, '')
FROM tableName as t2
GROUP BY Column1
/
Copied from here: https://github.com/jOOQ/jOOQ/issues/1277

How to check intersection of subqueries in query?

I have the next query:
SELECT c.client_code, a.account_num, m.account_close_date, u.uso, m.product_name
FROM accounts a INNER JOIN Clients c ON c.id = a.client_id INNER JOIN
Uso u ON c.uso_id = u.uso_id INNER JOIN Magazine m ON a.account_id = m.account_id
and I need to compare product_name with input parameter.
product_name and input parameter #s are comma-delimited strings.
I use next split function:
ALTER FUNCTION [dbo].[Split]
(
#s VARCHAR(max),
#split CHAR(1)
)
RETURNS #temptable TABLE (items VARCHAR(MAX))
AS
BEGIN
DECLARE #x XML
SELECT #x = CONVERT(xml,'<root><s>' + REPLACE(#s,#split,'</s><s>') + '</s></root>');
INSERT INTO #temptable
SELECT [Value] = T.c.value('.','varchar(20)')
FROM #X.nodes('/root/s') T(c);
RETURN
END;
I think that I need to check the intersection of tables, which I will receive after split of product_name and after split of input parameter. I trid to do this:
WHERE (select * from dbo.Split(m.product_name, ';')
INTERSECT select * from dbo.Split('product1;product2',';'))
is not null
But it does not work quite right. Please, help me.
INTERSECT requires the same column output and is used like UNION or EXCEPT: not in the WHERE clause
Just JOIN onto the udf
...
INNER JOIN
Magazine m ON a.account_id = m.account_id
INNER JOIN
dbo.Split(#parameter, ';') CSV ON m.productname = CSV.items
If you need to split m.productname, if you can't fix the design, use CROSS APPLY
...
INNER JOIN
Magazine m ON a.account_id = m.account_id
CROSS APPLY
dbo.Split(m.productname, ';') WTF
INNER JOIN
dbo.Split(#parameter, ';') CSV ON WTF.items = CSV.items
However, JOIN and INTERSECT give different results if #parameter has duplicated values. Add a DISTINCT to the UDF for example to get around this. Or change the udf JOIN into EXISTS