delete all the child rows in sql table by parentid - sql

I have a table from which I create a tree with multiple levels and parents. The table structure looks like this.
When I delete the "TitleID", I want all the children and even the grandchildren to be deleted.
What is the easiest way to do such in sql.
If I simple delete with "where ParentID=TitleID", only children with level 1 depth are deleted.

DECLARE #TitleId INT
SELECT ##TitleId = 2
;WITH results AS(
SELECT TitleId
FROM myTable
WHERE TitleId = #TitleId
UNION ALL
SELECT t.TitleId
FROM myTable t
INNER JOIN ret r ON t.ParentID = r.TitleId
)
DELETE FROM myTable WHERE TitleId IN (SELECT TitleId FROM results )

To handle tree structured data in relational database, you can add another column FullID, which contains value like 1.1.3. Then what you need is just a simple where clause WHERE FullID LIKE '1.1.%' if you want to delete node 1.1 and it's children.
The value of FullID can be generated by a stored procedure (for old data), or better by your application (for new data).

Related

Print unreferenced orphans from single table

I have a table (oracle database if it's important) that looks like this:
NAME VALUE
parent.1 aa1234
parent.2 bb1234
child.3H hh1234
child.2B bb1234
child.6P oo6666
parent.3 hh1234
child.1A aa1234
child.5K ee9999
child.2C bb1234
child.1A aa1234
child.3G hh1234
The table contains parents and children in pretty random order. They referencing each other by the VALUE column. A parent has same string value as it's child. Parents usually have one or more children, so parent and it's children will have exact same value.
This is an example, but it's valid to distinguish parent from child by substring like '%parent%' or like '%child%'. Both NAME and VALUE columns are NVARCHARS2(255).
I'm trying to find orphans - children that don't have a parent by the value (in the example child.6p and child.5K). Is it possible in one query or script?
You can use not exists as follows:
SELECT T.NAME, T.VALUE
FROM YOUR_TABLE T
WHERE T.NAME LIKE '%child%'
AND NOT EXISTS (SELECT 1
FROM YOUR_TABLE T1
WHERE T1.NAME LIKE '%parent%'
AND T.VALUE = T1.VALUE);
select * from tab C
where NAME LIKE ('child%')
AND NOT EXISTS
( SELECT 1 FROM TAB P WHERE
P.NAME LIKE ('parent%')
AND C.VAL = P.VAL
)
SQL Fiddel Demo

Identify Parent Child records using oracle SQL and avoid merge

I have a requirement to find Parent Child Accounts using SQL query and avoid the merge process if the survivor is Child and Loser is Parent.
I have records in the table x in the following format
Survivor Loser
400-GIZ-514 400-1729E3
Table x is a temporary table and the records in them are stored in base tables
In the base table the relationship between these 2 records is
ROW_ID PAR_OU_ID
Parent 400-1729E3 NULL
Child 400-GIZ-514 400-1729E3
Please help me with the query to identify these type of records and flag them so that they will be not be picked up the nightly process for merge.
Should be able to remove records from your temp table using
DELETE FROM tablex
WHERE EXISTS (
SELECT 1
FROM basetable
WHERE basetable.row_id = tablex.survivor
AND basetable.par_ou_id = tablex.loser
)
This query will only retrieve records where the row has no matching parent:
SELECT * FROM BASE_TABLE A
WHERE NOT EXISTS (SELECT 1 FROM BASE_TABLE B WHERE A.PAR_OU_ID = B.ROW_ID)

Join a table to itself

this is one on my database tables template.
Id int PK
Title nvarchar(10) unique
ParentId int
This is my question.Is there a problem if i create a relation between "Id" and "ParentId" columns?
(I mean create a relation between a table to itself)
I need some advices about problems that may occur during insert or updater or delete operations at developing step.thanks
You can perfectly join the table with it self.
You should be aware, however, that your design allows you to have multiple levels of hierarchy. Since you are using SQL Server (assuming 2005 or higher), you can have a recursive CTE get your tree structure.
Proof of concept preparation:
declare #YourTable table (id int, parentid int, title varchar(20))
insert into #YourTable values
(1,null, 'root'),
(2,1, 'something'),
(3,1, 'in the way'),
(4,1, 'she moves'),
(5,3, ''),
(6,null, 'I don''t know'),
(7,6, 'Stick around');
Query 1 - Node Levels:
with cte as (
select Id, ParentId, Title, 1 level
from #YourTable where ParentId is null
union all
select yt.Id, yt.ParentId, yt.Title, cte.level + 1
from #YourTable yt inner join cte on cte.Id = yt.ParentId
)
select cte.*
from cte
order by level, id, Title
No, you can do self join in your table, there will not be any problem. Are you talking which types of problems in insert, update, delete operation ? You can check some conditions like ParentId exists before adding new record, or you can check it any child exist while deleting parent.
You can do self join like :
select t1.Title, t2.Title as 'ParentName'
from table t1
left join table t2
on t1.ParentId = t2.Id
You've got plenty of good answers here. One other thing to consider is referential integrity. You can have a foreign key on a table that points to another column in the same table. Observe:
CREATE TABLE tempdb.dbo.t
(
Id INT NOT NULL ,
CONSTRAINT PK_t PRIMARY KEY CLUSTERED ( Id ) ,
ParentId INT NULL ,
CONSTRAINT FK_ParentId FOREIGN KEY ( ParentId ) REFERENCES tempdb.dbo.t ( Id )
)
By doing this, you ensure that you're not going to get garbage in the ParentId column.
Its called Self Join and it can be added to a table as in following example
select e1.emp_name 'manager',e2.emp_name 'employee'
from employees e1 join employees e2
on e1.emp_id=e2.emp_manager_id
I have seen this done without errors before on a table for menu hierarchy you shouldnt have any issues providing your insert / update / delete queries are well written.
For instance when you insert check a parent id exists, when you delete check you delete all children too if this action is appropriate or do not allow deletion of items that have children.
It is fine to do this (it's a not uncommon pattern). You must ensure that you are adding a child record to a parent record that actually exists etc., but there's noting different here from any other constraint.
You may want to look at recursive common table expressions:
http://msdn.microsoft.com/en-us/library/ms186243.aspx
As a way of querying an entire 'tree' of records.
This is not a problem, as this is a relationship that's common in real life. If you do not have a parent (which happens at the top level), you need to keep this field "null", only then do update and delete propagation work properly.

Nested query using while condition - sql

I need to do a nested query on a single table. Each row is potentially the parent or child of another row.
Is it possible to do this with a single select statement? Ive started using this statement but it only goes down one level.
select * from myTable where parent_id in
(select id from myTable where name = 'manager' )
This select however will only go down one level. If a row has multiple children they will be ignored. (In the table each row has an Id field , if a row has a parent then the parents Id value will be in the child's parent_Id field. )
If i could include a while loop in the SQL which would always check to see if the returned Id was a parent or not and if it was check and see if any other row was its child by checking the other rows parent_Id. However i m concerned this would take alot of cycles to eventually find all parent child relationships. Any suggestions? Thanks
using Oracle db
I think you are looking for a hierarchical query like this:
select * from mytable
connect by prior id = parent_id
start with name = 'Manager';
(A "nested table" is something else entirely.)

how to delete duplicates from a database table based on a certain field

i have a table that somehow got duplicated. i basically want to delete all records that are duplicates, which is defined by a field in my table called SourceId. There should only be one record for each source ID.
is there any SQL that i can write that will delete every duplicate so i only have one record per Sourceid ?
Assuming you have a column ID that can tie-break the duplicate sourceid's, you can use this. Using min(id) causes it to keep just the min(id) per sourceid batch.
delete from tbl
where id NOT in
(
select min(id)
from tbl
group by sourceid
)
delete from table
where pk in (
select i2.pk
from table i1
inner join table i2
on i1.SourceId = i2.SourceId
)
good practice is to start with
select * from … and only later replace to delete from …