SQL How to add values of a select statement to a varchar - sql

I'm writing a function that returns the names of a child table's one column's values in one varchar.
The relation is:
I have a parent table called Activity.
And a child table in N-1 relation with table Activity, called ActivityObjective.
And a third table where I keep the names of the objectives, called Objective.
This is the query that I make. This returns the names of the objectives of a specific Activity with ActivityID = #ActivityID
SELECT o.ObjectiveName
FROM Activity a
INNER JOIN ActivityObjective ao ON a.ActivityID = ao.ActivityID
INNER JOIN Objective o ON o.ObjectiveID = ao.ObjectiveID
WHERE a.ActivityID = #ActivityID
This returns something like:
ObjectiveName
|-------------------|
objName1
objName2
objName3
My aim is no have a varchar "objName1, objName2, objName3". I cannot create a temp table because I'm working in a function.

You will need to adjust the following to match what you specifically wanted, but this is a start:
Select substring((
SELECT (', ' + o.ObjectiveName)
FROM Activity a
INNER JOIN ActivityObjective ao ON a.ActivityID = ao.ActivityID
INNER JOIN Objective o ON o.ObjectiveID = ao.ObjectiveID
WHERE a.ActivityID = #ActivityID
FOR XML PATH( '' )
), 3, 1000 )

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

Create recursive query where column values need to get based on another column | ORACLE

I have two tables where one table has list of issues and another table has its parent issue in form of issue id.
I am only mentioning required columns
1st table
ID, ISSUENUM, PROJECTKEY
2nd Table
JSON_VALUE has parent_id which is ID from 1st table
END result expectation
ID, ISSUENUM, PROJECT KEY, PARENT_ISSUENUM, PARENT_PROJECT_KEY
I have query till this point, but unable to make hierarchical/ recursive query
(select json_value(EP.JSON_VALUE, '$.parent_id' RETURNING NUMBER)as xyz
from JIR.ENTITY_PROPERTY EP where EP.ENTITY_ID = JI.ID AND EP.ENTITY_NAME = 'IssueProperty'
AND json_exists(EP.JSON_VALUE, '$.parent_id'))as parent_id
from jir.project p,jir.jiraissue JI
where p.id = ji.project
and (p.pkey = 'ABCDEF' OR p.pkey = 'UVWXYZ')
How to use this ID which I have as column parent_id and use it to get parent_issue_num and parent_project_key
I solved it myself. I improved the query on getting parent_id and get parent_key using column query itself
select JI.ID,
(select P.PKEY||'-'||ji2.issuenum
from JIR.ENTITY_PROPERTY EP
inner join jir.jiraissue JI2 on ji2.id=json_value(EP.JSON_VALUE, '$.parent_id' RETURNING NUMBER)
inner join jir.project p2 on p2.id=ji2.project
where EP.ENTITY_ID = JI.ID AND EP.ENTITY_NAME = 'IssueProperty'
AND json_exists(EP.JSON_VALUE, '$.parent_id'))as parent_id
from jir.project p,jir.jiraissue JI
where p.id = ji.project
and (p.pkey = 'ABCDEF' OR p.pkey = 'UVWXYZ')
This small change resolved the issue
inner join jir.jiraissue JI2 on ji2.id=json_value(EP.JSON_VALUE, '$.parent_id' RETURNING NUMBER)
inner join jir.project p2 on p2.id=ji2.project

SELECT and JOIN column not in Group by function

I have to join two different table to get my result.
The table 'Resource' it is simple, while the table 'Dimension.[Code]' contains, among the others, a column with different values (i.e :
Code
SILO
GRADE
OTHER 1
OTHER2
This is the reason why a join twice that column to get two different columns called GRADE and SILO.
Now, I have a query that selects the maximum value of a grade within the group as follows:
`SELECT
R.[ID] -- If I inserted that here, it is not working obviously.
-- This cannot But this is the additional column I need (see later)
DD_SILO.[Value] DIR ,
max(R.[GRADE]) GRADE_DIR
FROM [Resource] R
LEFT JOIN
Dimension DD_SILO ON R.[ID] = DD_SILO.[ID] AND DD_SILO.[Code] = 'SILO'
group by DD_SILO.[Value]'
What I need is basically to have, beside GRADE AND SILO, also the ID name, which is contained into the [Resource] table.
Please notice that [Resource].ID = [Dimension].ID
I would have solved the problem with ROW_NUMBER () to select the highest within the group, avoiding then then 'group by', but as the query has to be inserted in a bigger one, that would take too much time to run. I am using Microsoft SQL Server 2016.
Could you use a virtual table something like: -
`
select
a.max_grade_silo,
a.max_grade_value,
(select max(r.id)
from [resource] r,
[dimension] d
where r.[ID] = d.[ID] and
d.[CODE]= 'SILO' and
r.[GRADE] = a.[max_grade_value]
),
max_grade_silo a
from
(SELECT
DD_SILO.[Value] DIR ,
max(R.[GRADE]) GRADE_DIR
FROM [Resource] R
LEFT JOIN
Dimension DD_SILO ON R.[ID] = DD_SILO.[ID] AND DD_SILO.[Code] = 'SILO'
group by DD_SILO.[Value]
) temp_result (max_grade_silo, max_grade_value)
'
Probably better to look at normalizing the tables?
SELECT
MAX(R.[ID]) as ID ,
DD_SILO.[Value] DIR ,
max(R.[GRADE]) GRADE_DIR
FROM [Resource] R
LEFT JOIN
Dimension DD_SILO ON R.[ID] = DD_SILO.[ID] AND DD_SILO.[Code] = 'SILO'
group by DD_SILO.[Value]

How to Retrieve Column Headers of a Select Query?

How it is possible to retrieve column headers of a select query as a single column in SQL Server ? (it is preferred to retrieve data type of columns )
Query example:
select a.PartId, a.PartName, b.GroupName
from Parts as a
inner join Groups as b on a.GroupRef = b.GroupId
Expected result:
Columns
--------
PartId
PartName
GroupName
Starting from SQL Server 2012+ you can use sys.dm_exec_describe_first_result_set to get all metadata about result set:
DBFiddle Demo
DECLARE #tsql NVARCHAR(MAX) =
N'select a.PartId , a.PartName , b.GroupName
from Parts as a inner join Groups as b
on a.GroupRef = b.GroupId';
SELECT name AS [Columns]
FROM sys.dm_exec_describe_first_result_set(#tsql, NULL, 1)
One way is to create a temporary table with the schema of resultset and then query tempdb's schema table to get the column names and details. You can get all needed details.
select a.PartId , a.PartName , b.GroupName into #yourtable
from Parts as a inner join Groups as b
on a.GroupRef = b.GroupId
where 1=2
SELECT c.name as columnname,t.name as datatype
FROM tempdb.sys.columns c
inner join tempdb.sys.systypes as t on t.xtype = c.system_type_id
WHERE [object_id] = OBJECT_ID(N'tempdb..#yourtable');
SELECT 'PartId', 'PartName', 'GroupName'
UNION ALL
select a.PartId , a.PartName , b.GroupName
from Parts as a inner join Groups as b
on a.GroupRef = b.GroupId

SQL: Want to alter the conditions on a join depending on values in table

I have a table called Member_Id which has a column in it called Member_ID_Type. The select statement below returns the value of another column, id_value from the same table. The join on the tables in the select statement is on the universal id column. There may be several entries in that table with this same universal id.
I want to adjust the select statement so that it will return the id_values for entries that have member_id_type equal to '7'. However if this is null then I want to return records that have member_id_type equal to '1'
So previously I had a condition on the join (commented out below) but that just returned records that had member_id_type equal to '7' and otherwise returned null.
I think I may have to use a case statement here but I'm not 100% sure how to use it in this scenario
SELECT TOP 1 cm.Contact_Relation_Gid,
mc.Universal_ID,
mi.ID_Value,
cm.First_Name,
cm.Last_Name,
cm.Middle_Name,
cm.Name_Suffix,
cm.Email_Address,
cm.Disability_Type_PKID,
cm.Race_Type_PKID,
cm.Citizenship_Type_PKID,
cm.Marital_Status_Type_PKID,
cm.Actual_SSN,
cm.Birth_Date,
cm.Gender,
mc.Person_Code,
mc.Relationship_Code,
mc.Member_Coverage_PKID,
sc.Subscriber_Coverage_PKID,
FROM Contact_Member cm (NOLOCK)
INNER JOIN Member_Coverage mc (NOLOCK)
ON cm.contact_relation_gid = mc.contact_relation_gid
AND mc.Record_Status = 'A'
INNER JOIN Subscriber_Coverage sc (NOLOCK)
ON mc.Subscriber_Coverage_PKID = sc.Subscriber_Coverage_PKID
AND mc.Record_Status = 'A'
LEFT outer JOIN Member_ID mi ON mi.Universal_ID = cm.Contact_Gid
--AND mi.Member_ID_Type_PKID='7'
WHERE cm.Contact_Relation_Gid = #Contact_Relation_Gid
AND cm.Record_Status = 'A'
Join them both, and use one if the other is not present:
select bt.name
, coalesce(eav1.value, eav2.value) as Value1OrValue2
from BaseTable bt
left join EavTable eav1
on eav1.id = bt.id
and eav1.type = 1
left join EavTable eav2
on eav2.id = bt.id
and eav2.type = 2
This query assumes that there is never more than one record with the same ID and Type.