Select data from child parent relationship of the same table - sql

I have below table schema:
create table location_master (id serial,name character varying,parent_id integer);
INSERT INTO location_master (name,parent_id)
VALUES
('Bombay',1)
, ('Ahmedabad',1)
, ('Surat',1)
, ('Vapi',3)
, ('Navarangpura',2);
From above table I want to find the path from source id = 1 to destination id = 4. So the expected result is as below:
Here destination id = 4. Which has parent_id = 3. On words id = 3 has parent_id = 1 and so on.
Example:
A user wants to send a parcel from id = 1 to id = 4. Routing path for the parcel is decided by this table. When a user selects source id = 1 and destination id = 4 then the query automatically finds the route from child-parent relationship. Parcel will go through 1,3,4 path.
I tried SELF JOIN for this but did not get the expected result.

Thanks joop. I search for Recursive Query and got the solution as I want:
WITH RECURSIVE demo AS (
SELECT parent_id
FROM location_master
WHERE id = <destination_id>
UNION ALL
SELECT a.parent_id
FROM location_master a
JOIN demo b ON(a.id = b.parent_id))
SELECT DISTINCT location_master.* FROM location_master JOIN demo
on location_master.id = demo.parent_id WHERE demo.parent_id != 0
UNION
SELECT location_master.* FROM location_master WHERE id = <destination_id>
ORDER BY id ;

Related

Select rows having value combination listed in another table

I have tables:
Result containing 5 columns: result_id, num_1, num_2, num_3, num_4
Ref containing 4 columns: num_1, num_2, num_3, num_4
Columns num contain random int in range of 1-9
Aim of exercise is to display all result_id from Result table which have num values combination present in Ref table and to display result_id which have not met combination criteria.
I've been trying left joining ref to result, but unfortunately no success. Could you please share some light how to deal with it?
If you want the result_id for which combination exists in the ref table then use following JOIN query:
select distinct r.result_id
from results r
join ref on r.num_1 = ref.num_1 and r.num_2 = ref.num_2
and r.num_3 = ref.num_3 and r.num_4 = ref.num_4
If you want the result_id for which combination do not exists in REF table then use the LEFT JOIN as follows:
select r.result_id
from results r
left join ref on r.num_1 = ref.num_1 and r.num_2 = ref.num_2
and r.num_3 = ref.num_3 and r.num_4 = ref.num_4
where ref.num_1 is null -- or use PK / Not nullable column of REF table here
Assuming you want the columns to "line up" and you want to add a flag to the result_id in the first table, then use exists:
select t1.*,
(case when exists (select 1
from table2 t2
where t2.n1 = t1.n1 and t2.n2 = t1.n2 and t2.n3 = t1.n3 and t2.n4
)
then 'present' else 'not present'
end) as flag
from t2;

remove Union from query

I have query to get category and subcategories of same category. I used below query:
Select Id from category where name like '%events%' and deleted = 0 and published = 1
UNION
SELECT Id from category where parentcategoryid = (Select id from category where name like '%events%' and deleted = 0 and published = 1)
I do not want to use UNION, want to use Join only. But not getting how i can achieve. Below is the table structure. Please help me. thanks in Advance
The following might solve your problem:
DECLARE #t TABLE (id int, name varchar(20), parentcatid varchar(200))
insert into #t values(23,'Christmas', 34)
,(29,'Birthday', 34)
,(31,'New year', 34)
,(34,'Events', 0)
,(35,'gfrhrt', 0)
;WITH cte AS(
Select Id from #t
where name like '%events%' --and deleted = 0 and published = 1
),
cte2 AS (
SELECT a.id AS tId, cpa.id, cId2.id AS idPa
from #t a
LEFT JOIN cte AS cId ON cId.Id = a.Id
FULL OUTER JOIN #t AS cPa ON cPa.parentcatid = cId.Id
LEFT JOIN cte cId2 ON cId2.id = cPa.id
WHERE cId.Id IS NOT NULL OR cPa.Id IS NOT NULL
)
SELECT id
FROM cte2
WHERE tId IS NOT NULL
OR id = idPa
The idea is to get all required IDs within the cte and then get all categories, where either ID oder ParentID match the IDs from the cte. However, depending on the size of your table, you might want to add further filters to the cte.

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

SQL Query -IF EXISTS and WITH

Hi have a stored procedure with WITH keyword that returns a resultset as follows
WITH p as(...),
mp as (select *, x.name from p left join x on ...)
Now i want to say
IF EXISTS (select * from mp where pid is not null and id != pid)
THEN
BEGIN
SELECT * FROM cp left join mp on ...
END
ELSE
BEGIN SELECT * FROM mp where...
END
Here i am facing some syntax error this select should be returned back from stored procedure
UPDATE
I have put it as follows
SELECT DISTINCT *
FROM (
--get all parent records that matches RIDE ID
SELECT * FROM mp WHERE pid is null or pid = id
UNION --get parent of a child that matches RIDE ID
SELECT pl.* [i have specified exact same columns in this select]
FROM pl
left join mp on pl.plc_id = mp.PrimaryPlacementId
left join reg on reg.usr_id = mp.plc_usr and isnull(reg.usr_isdeleted, 0) = 0 --and reg.usr_active = 1
left join ut on ut.cut_id = mp.plc_unit
left join f on f.fac_id = mp.plc_facility and isnull(f.fac_isdeleted, 0) = 0
left join s on s.sem_id = mp.plc_semester and isnull(s.sem_isdeleted, 0) = 0
WHERE mp.pid != id AND mp.pid is not null
) x
This one seems to work ok - basically pid contains the parent id
My mp=pl table has the following structure
id | name | pid
1 | sam | 1
2 | sid | 1
so basically first is the parent record and second is the child record.
so what i want is - if i search 'sam' then record 1 is returned
and if i search 'sid' again record one is returned
i.e if u search by parent id or child id the parent record should be returned or those whose pid is null

How do I iterate through hierarchical data in a Sql Server 2005 stored proc?

I have a SqlServer2005 table "Group" similar to the following:
Id (PK, int)
Name (varchar(50))
ParentId (int)
where ParentId refers to another Id in the Group table. This is used to model hierarchical groups such as:
Group 1 (id = 1, parentid = null)
+--Group 2 (id = 2, parentid = 1)
+--Group 3 (id = 3, parentid = 1)
+--Group 4 (id = 4, parentid = 3)
Group 5 (id = 5, parentid = null)
+--Group 6 (id = 6, parentid = 5)
You get the picture
I have another table, let's call it "Data" for the sake of simplification, which looks something like:
Id (PK, int)
Key (varchar)
Value (varchar)
GroupId (FK, int)
Now, I am trying to write a stored proc which can get me the "Data" for a given group. For example, if I query for group 1, it returns me the Key-Value-Pairs from Data where groupId = 1. If I query for group 2, it returns the KVPs for groupId = 1, then unioned with those which have groupId = 2 (and duplicated keys are replaced).
Ideally, the sproc would also fail gracefully if there is a cycle (ie if group 1's parent is group 2 and group 2's parent is group 1)
Has anyone had experience in writing such a sproc, or know how this might be accomplished?
Thanks guys, much appreciated,
Alex
This can be accomplished using recursive queries and CTEs
;WITH KeyValue AS
(
SELECT G.Id, G.Name, D.Key, D.Value, 0 AS level
FROM Group G
LEFT JOIN Data D ON G.Id = D.GroupID
WHERE G.Id = #your_top_level_root
UNION ALL
SELECT G.Id, G.Name, D.Key, D.Value, K.level + 1
FROM KeyValue K
JOIN Group G ON G.ParentId = K.Id
LEFT JOIN Data D ON G.Id = D.GroupID
)
SELECT * FROM KeyValue