Dynamic column in oracle sql - sql

I want to query in database for some ledgername (like child),ledgergroupname (like parent,it's parent of ledgername) and all ascending parent's of ledgergroupname (or ledgername).Data i am searching from ACC_LEDGER table where ledgername and it's immediate parent termed as ledgergroupname are saved.Ascending parent of ledgergroupname are saved in ACC_LEDGERGROUP table.
sql--
select
pp.Ledgercode,
pp.Ledgername,
pp.Ledgergroupcode,
pp.Ledgergroupname,
(select Acc_Ledgergroup.Parentname from Acc_Ledgergroup where Acc_Ledgergroup.Ledgergrpcode=pp.Ledgergroupcode) as PARENTNAME
from
(select
LED.LEDGERCODE,
Led.Ledgername,
Led.Ledgergroupcode,
Led.Ledgergroupname
from ACC_LEDGER LED where Led.Ledgercode IN ('01003024007','01003024019'))pp
it gives me result--
what i want is --
so for every ledger i want to show parent upto root (it's level is different for different ledger means for some ledger it has 7 upper parent's to reach "root" parent).
I am trying to query something like this(it's for your understanding)--
select
pp.Ledgercode,
pp.Ledgername,
pp.Ledgergroupcode,
pp.Ledgergroupname,
(select Acc_Ledgergroup.Parentname from Acc_Ledgergroup where Acc_Ledgergroup.Ledgergrpcode=pp.Ledgergroupcode) as PARENTNAME
while(parentname != root)
{
select parent name from Ledger group
}
from the_table
So column selection from table or join of table is not fixed,it's depend on how much level of parent i have,how can i do that in oracle sql?

Generally this kind of problems can be solved with hierarchical queries (using CONNECT BY), however in Oracle a query cannot have a variable number of columns. As a workaround you can use sys_connect_by_path to concatenate all levels using some separator:
select sys_connect_by_path(Ledgergroupname, '/')
from Acc_Ledgergroup
where Ledgergroupname = 'root'
start with Ledgercode in ('01003024007', '01003024019')
connect by prior Ledgercode = Ledgergroupcode

Related

How to represent a tree structure with ORDER BY OR GROUP BY

Given a table 'TEMPLATES'(with columns ID,NAME,IS_MASTER,MASTER_ID etc) which describes multiple content management system elements e.g. masters, templates etc.
The column IS_MASTER filters the master-docs. I want to filter all master-docs and the associated elements(documents), which point to the master over the 'MASTER_ID' column of the same table but I want to order the rows one after another for example after a result row which shows a master should be listed the elements, which point to this master (and not all rows mixed up like in the screenshot) :
But I can only do it in this way, I don't know how to order or group by
SELECT x.*,x.ROWID FROM TEMPLATE x
WHERE IS_MASTER IN (1) OR MASTER_ID IS NOT NULL
You could do this:
select *
from templates
order by nvl(master_id, id);
This would tell the database to sort by master_id, and if that column is empty (NULL) to use the id. This way the master and its children are sorted together.
Alternatively you can use a hierarchical query:
select *
from templates
start with master_id is null
connect by master_id = prior id;

Find latest object in hierarchy where the latest isn't marked as deleted

I have two tables (of interest). The first table is a simple hierarchy. Each row has an ID, and a parent ID. Obviously, the parent ID can be NULL when we reach the top of that particular hierarchy. (We store multiple trees here, so there can be multiple NULL parents, but that's probably not important here.)
The second table has objects that have a non-unique identifier, for example a name, a timestamp, and a reference to the first table to indicate where on the hierarchy it sits.
Let's say the first table has a hierarchy of /A/B/C, and the second has a bunch of objects named "Foo". If I'm trying to get the latest Foo in /A/B, then I don't want to get anything from C. This seems straightforward enough. However, if the latest "Foo" in /A/B is marked in the database with a field saying it is deleted, e.g., status = 'deleted', I want to instead get the latest "Foo" in /A even if there are other "Foo" objects with earlier timestamps in /A/B.
Is this possible to do in a CTE? Or do I have to resort to a stored procedure to get this type of logic? I'm already using some stored procedures just for refactoring purposes, so that's not a barrier, but if I can do this in a simpler manner that I'm missing, that may be better (including for performance).
Since that's probably a bit vague, I put this on SQLFiddle. If I add in the override on line 24 of the schema, I should get that as the output. However, if I also add the deleted object in 26, I need to get back to the "update in /A" as the output.
I would extend your code with one intermediate step:
with recursive _rpath as (
select
0 as level,
id, parentid, name
from path
where id = 5 -- this would be filled in later
union all
select
child.level + 1 as level,
parent.id, parent.parentid, parent.name
from _rpath child
join path parent on child.parentid = parent.id
) , c AS (
select
rp, d, d.status
, ROW_NUMBER() OVER(PARTITION BY d.pathid ORDER BY d.creation DESC) AS rn
from data d
join _rpath rp
on rp.id = d.pathid
), datapaths AS (
SELECT *
FROM c
WHERE rn =1
AND status != 'deleted'
)
select dp.rp, dp.d
from datapaths dp
left join datapaths dpNext
on (dpNext.rp).level < (dp.rp).level or
((dpNext.rp).level = (dp.rp).level
and (dpNext.d).creation > (dp.d).creation)
where (dpNext.d).id is null;
DBFiddle Demo
How it works:
-- calculate node number for each pathid sort by creation descending
-- newest one gets always 1
ROW_NUMBER() OVER(PARTITION BY d.pathid ORDER BY d.creation DESC)
-- get only first for each pathid but omit if it is 'deleted'
WHERE rn =1
AND status != 'deleted'

Determining the Level of Hierarchy in SQL

I've a data of an ERP Standard Feature called Bill of Material, Where It'll have a tree Structure.
I has 4 column as Unique_Id,from,is_main and srno
So here 1st Column is an unique Id,2nd Column indicated its Parent row, 3rd Column Indicates whether it has a sub set or not and 4th is just another series of the Subset.
Link for the Screenshots : Screenshots
So Picture indicates the Hierarchy of the above data.
So I need to get the Answer as Level of Hierarchy. As picture shows the Maximum of 4 stages of Hierarchy.
This is Sample query, You have to change according to you
WITH temp AS
(
SELECT A.Unique_Id, A.from, A.is_main , A.srno
FROM [dbo].[Your_Table_Name] A
UNION ALL
SELECT B.Unique_Id, A.from, B.is_main , B.srno
FROM temp AS B
INNER JOIN [dbo].[Your_Table_Name] A ON B.from= A.Unique_Id
WHERE A.from IS NOT NULL
)
SELECT * FROM temp

How to search on levelOrder values un SQL?

I have a table in SQL Server that contains the following columns :
Id Name ParentId LevelOrder
8 vehicle 0 0/8/
9 car 8 0/8/9/
10 bike 8 0/8/10/
11 House 0 0/11/
...
This creates a tree.
Say that I have the LevelOrder 0/8/, this should return only the car and bike rows, but how do I handle this in SQL Server?
I have tried :
Select * FROM MyTable WHERE LevelOrder >= '0/8/'
but that does not work.
The underscore character will guarantee at least one character comes after '0/8/', so you don't get a match on the "vehicle" row.
SELECT *
FROM MyTable
WHERE LevelOrder LIKE '0/8/_%'
This code allows you to select values that start with 0/8/
Select * FROM MyTable WHERE LevelOrder like '0/8/%'
Okay -
While #Joe's answer is the simplest and easiest to implement (and possibly better performing than what I'm about to propose...), there are some issues with update anomalies.
Specifically:
You already have a parentId column. You need to synchronize both this and the levelOrder column, or risk inconsistent data. (I believe this also violates 1NF, although my understanding of the exact definition is a little sketchy...)
levelOrder contains the entire heirarchy. If any one parent is moved, all children rows must have levelOrder modified to reflect this (potentially very messy).
In light of this, here's what I recommend:
Drop the levelOrder column, as its existence will (generally) cause problems.
Use a recursive CTE and the parentId column to build the heirarchy dynamically. Either leave the column where it is, or move it to a dedicated relationship table. Moving one parent then requires only one cell to be updated, and cannot result in any (data, not semantic) anomalies. The CTE should look similar to this form (will need to be adjusted for purpose):
WITH heir_parent (parentId, id) as (SELECT parentId, id
FROM table
WHERE id =
UNION ALL
SELECT b.parentId, b.id
FROM heir_parent as a
JOIN table as b
ON b.parentId = a.id)
At the moment, the CTE returns a list of all children of the given id, with their id and their immediate parent. It can be adjusted to return a number of other things as well - although I recommend that the CTE be used only to generate the relationship, and join externally to get the remaining data.

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.)