Hierarchical query outputs error - sql

Here is my code:
with tbl as
(
Select parent_b.BRANCH_ID, parent_b.BRANCH_CODE,
parent_b.BRANCH, parent_b.PARENT_BRANCH_ID
from table parent_b
Where parent_b.branch_Id = 1
UNION ALL
Select child_b.BRANCH_ID, child_b.BRANCH_CODE,
child_b.BRANCH, child_b.PARENT_BRANCH_ID
from table child_b
INNER JOIN tbl parent
ON parent.branch_id = child_b.branch_id
)
select * from tbl
OPTION(MAXRECURSION 32767)
Above code gets me error with this message:
The statement terminated. The maximum recursion 100 has been exhausted
before statement completion.
I checked the table, and there no rows where row points to himself (infinity).
Where is my problem?

There's a logical error in the recursive part of your CTE - the join condition:
ON parent.branch_id = child_b.branch_id
is linking the parent's branch_id directly to the child's branch_id, when it should be linking to the child's parent_branch_id - like so:
ON parent.branch_id = child_b.parent_branch_id
The following query should work:
with tbl as
(
Select parent_b.BRANCH_ID, parent_b.BRANCH_CODE,
parent_b.BRANCH, parent_b.PARENT_BRANCH_ID
from table parent_b
Where parent_b.branch_Id = 1
UNION ALL
Select child_b.BRANCH_ID, child_b.BRANCH_CODE,
child_b.BRANCH, child_b.PARENT_BRANCH_ID
from table child_b
INNER JOIN tbl parent
ON parent.branch_id = child_b.parent_branch_id
)
select * from tbl
OPTION(MAXRECURSION 32767)

Specify the maxrecursion option at the end of the query:
select *
from tbl
option (maxrecursion 0)

Related

how to delete repeated values in UNION query using count

Hello I have been trying to delete a repeated value on the following UNION query with the following results (image). How can I filter out the value LW_ID=8232 with AANTALLN =0. I need to find a way taht if in the first query AANTALLN >0 is found, then on the second part of the union query not insert it again. Thanks "
With LESEENHEIDLOOPBAAN as (
SELECT
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP,
Count(LH_ID) As AantalLln
FROM
LESEENHEID
INNER JOIN LOOPBAANLESEENHEID on (LH_LESEENHEID_FK = LE_ID)
INNER JOIN LOOPBAAN ON (LH_LOOPBAAN_FK = LB_ID)
WHERE
(
'2022/09/28' BETWEEN LB_VAN
AND LB_TOT
)
AND (
LE_ID in (8277, 8276, 8232)
)
GROUP BY
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP
),
LESEENHEIDLOOPBAANNULL AS (
SELECT
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP,
0 As AantalLln
FROM
LESEENHEID
where
LE_ID in (8277, 8276, 8232)
and EXISTS (
SELECT
*
FROM
LESEENHEIDLOOPBAAN
)
)
SELECT
*
FROM
LESEENHEIDLOOPBAAN
UNION
SELECT
*
FROM
LESEENHEIDLOOPBAANNULL ROWS 1000
Try this out using ROW_NUMBER:
SELECT * FROM (
SELECT
ROW_NUMBER () OVER (PARTITION BY LW_ID ORDER BY AANTALLN DESC) AS RN
,* FROM
(
SELECT * FROM
LESEENHEIDLOOPBAAN
UNION
SELECT
*
FROM
LESEENHEIDLOOPBAANNULL ROWS 1000
)
)
) WHERE RN = 1
This way you eliminate the duplicates.

Hierarchical error

Here is my code:
with t(branch_id, branch_code, branch, parent_branch_id, level) as
(
Select parent_b.BRANCH_ID, parent_b.BRANCH_CODE,
parent_b.BRANCH, parent_b.PARENT_BRANCH_ID, 0 as level
from table parent_b
Where parent_b.branch_Id is null--= 1
UNION ALL
Select child_b.BRANCH_ID, child_b.BRANCH_CODE,
child_b.BRANCH, child_b.PARENT_BRANCH_ID, (t.level+1)
from table child_b
INNER JOIN t parent
ON parent.branch_id = child_b.parent_branch_id
)
select * from t
And i get error in ouput. Where is the error, i can't find.
Error:
The multi-part identifier "t.level" could not be bound.
Change t.level to parent.level. You have given an alias to CTE as `parent'. you need to use that.
with t(branch_id, branch_code, branch, parent_branch_id, level) as
(
Select parent_b.BRANCH_ID, parent_b.BRANCH_CODE,
parent_b.BRANCH, parent_b.PARENT_BRANCH_ID, 0 as level
from table parent_b
Where parent_b.branch_Id is null--= 1
UNION ALL
Select child_b.BRANCH_ID, child_b.BRANCH_CODE,
child_b.BRANCH, child_b.PARENT_BRANCH_ID, (parent.level+1)
from table child_b
INNER JOIN t parent
ON parent.branch_id = child_b.parent_branch_id
)
select * from t

Incorrect Syntax Near Keyword 'OPTION' in CTE Statement

I get a "Incorrect syntax near keyword 'OPTION'" error when attempting to save a view in SQL Server 2008. I'm trying to add a MAXRECURSION option to the end of my common table expression. All the examples I've seen and working CTEs I've created before don't mind the "OPTION (MAXRECURSION 0)" at the end of the CTE.
Anyone see why I'm getting this error? The CTE works without the OPTION clause, although it reaches the maximum number of recursions (100).
WITH CTE AS
(
SELECT
CDay,
InvAcct,
BuyerCode,
PartNumber,
ROP,
ROP_ROQ,
DailyDemand,
StartingInvQty,
SchedDeliveryQty,
CAST(StartingInvQty - DailyDemand/2.0 AS decimal(18,4)) AS ProjInvQty
FROM
qryInventorySimulation
WHERE
MBC = 'B' AND
CDay = CAST(CAST(GETDATE()AS date) as datetime)
UNION ALL
SELECT
qryInventorySimulation.CDay,
qryInventorySimulation.InvAcct,
qryInventorySimulation.BuyerCode,
qryInventorySimulation.PartNumber,
qryInventorySimulation.ROP,
qryInventorySimulation.ROP_ROQ,
qryInventorySimulation.DailyDemand,
qryInventorySimulation.StartingInvQty,
qryInventorySimulation.SchedDeliveryQty,
CAST(CTE.ProjInvQty + qryInventorySimulation.SchedDeliveryQty - qryInventorySimulation.DailyDemand AS decimal(18,4)) AS ProjInvQty
FROM
qryInventorySimulation INNER JOIN CTE ON qryInventorySimulation.InvAcct = CTE.InvAcct AND qryInventorySimulation.PartNumber = CTE.PartNumber AND qryInventorySimulation.CDay = DATEADD(d,1,CTE.CDay)
WHERE
qryInventorySimulation.CDay <= DATEADD(d,120,GETDATE())
)
SELECT * FROM CTE
OPTION (MAXRECURSION 0);
You can't apply this option within the view. You would need to apply it to the query calling the view. e.g.
CREATE VIEW dbo.V
AS
WITH CTE AS
( SELECT 1 AS A
UNION ALL
SELECT A + 1
FROM CTE
WHERE A < 50
)
SELECT *
FROM CTE;
GO
SELECT *
FROM dbo.V
OPTION (MAXRECURSION 0);
If you think of a view more as a stored subquery than a stored query (yes it can be called on it's own but it is not necessarily), and remember that its definition is expanded out into the main query (unless you are using NOEXPAND - which you could not on a view that contained a recursive CTE anyway), so in essence you are trying to do something like this:
WITH RecursiveCTE AS (...)
SELECT *
FROM T
INNER JOIN
( SELECT *
FROM RecursiveCTE
OPTION (MAXRECURSION 0)
) c
ON c.SomeField = T.SomeField;
Whereas the correct syntax would be:
WITH RecursiveCTE AS (...)
SELECT *
FROM T
INNER JOIN
( SELECT *
FROM RecursiveCTE
) c
ON c.SomeField = T.SomeField;
OPTION (MAXRECURSION 0)

With clause subquery availablility for the entire SQL statement in Oracle

I am trying to write a SQL statement which reuses the subquery of the With clause multiple times in Oracle.
With mySubQ as (
...
)
Select Something
From SomeTable,
(
Select *
From mySubQ
where mySubQ.Something >= 0
) newSubQ
where mySubQ.Something = SomeTable.Something
This gives me error - ORA-32034 unsupported use of WITH clause
What am I missing?
You need to join with mySubQ, not just define it.
WITH mySubQ AS (...)
SELECT Something
FROM SomeTable
JOIN mySubQ ON mySubQ.Something = SomeTable.Something
WHERE mySubQ.Something >= 0
If you put the query of mySubQ in a subquery, you can't reference mySubQ in the WHERE clause of the main query. Each level of query can only access tables in its own FROM and JOIN clauses, not those of subqueries.
Here is the error: where mySubQ.Something = SomeTable.Something.
The bottom query selects from SomeTable and from the subquery with alias newSubQ,
so mySubQ.Something is not known in this context.
If something is a real column name, not only a "placeholder in the pseudocode", then there is also another error here: Select Something - the column is ambiguous, because both sometable and the subquery have this column.
Try this query:
With mySubQ as (
SELECT * FROM sometable
)
Select newSubQ.Something
From SomeTable,
(
Select *
From mySubQ
where mySubQ.Something >= 0
) newSubQ
where newSubQ.Something = SomeTable.Something
;
Demo --> http://www.sqlfiddle.com/#!4/88855/12
This demo contains also another example of using WITH clause:
WITH mySubQ AS (
SELECT *
FROM sometable
),
mySubQ_1 AS (
SELECT *
FROM mySubQ
WHERE somethingelse = 1
),
mySubQ_2 AS (
SELECT *
FROM mySubQ
WHERE something between 2 AND 5
)
SELECT *
FROM sometable s, mySubQ_1 m1,
(
SELECT * FROM mySubQ_2
WHERE something < 10
) m2
WHERE s.something = m1.something
AND m1.somethingelse = m2.somethingelse

Can you create nested WITH clauses for Common Table Expressions?

WITH y AS (
WITH x AS (
SELECT * FROM MyTable
)
SELECT * FROM x
)
SELECT * FROM y
Does something like this work? I tried it earlier but I couldn't get it to work.
While not strictly nested, you can use common table expressions to reuse previous queries in subsequent ones.
To do this, the form of the statement you are looking for would be
WITH x AS
(
SELECT * FROM MyTable
),
y AS
(
SELECT * FROM x
)
SELECT * FROM y
You can do the following, which is referred to as a recursive query:
WITH y
AS
(
SELECT x, y, z
FROM MyTable
WHERE [base_condition]
UNION ALL
SELECT x, y, z
FROM MyTable M
INNER JOIN y ON M.[some_other_condition] = y.[some_other_condition]
)
SELECT *
FROM y
You may not need this functionality. I've done the following just to organize my queries better:
WITH y
AS
(
SELECT *
FROM MyTable
WHERE [base_condition]
),
x
AS
(
SELECT *
FROM y
WHERE [something_else]
)
SELECT *
FROM x
With does not work embedded, but it does work consecutive
;WITH A AS(
...
),
B AS(
...
)
SELECT *
FROM A
UNION ALL
SELECT *
FROM B
EDIT
Fixed the syntax...
Also, have a look at the following example
SQLFiddle DEMO
These answers are pretty good, but as far as getting the items to order properly, you'd be better off looking at this article
http://dataeducation.com/dr-output-or-how-i-learned-to-stop-worrying-and-love-the-merge
Here's an example of his query.
WITH paths AS (
SELECT
EmployeeID,
CONVERT(VARCHAR(900), CONCAT('.', EmployeeID, '.')) AS FullPath
FROM EmployeeHierarchyWide
WHERE ManagerID IS NULL
UNION ALL
SELECT
ehw.EmployeeID,
CONVERT(VARCHAR(900), CONCAT(p.FullPath, ehw.EmployeeID, '.')) AS FullPath
FROM paths AS p
JOIN EmployeeHierarchyWide AS ehw ON ehw.ManagerID = p.EmployeeID
)
SELECT * FROM paths order by FullPath
we can create nested cte.please see the below cte in example
;with cte_data as
(
Select * from [HumanResources].[Department]
),cte_data1 as
(
Select * from [HumanResources].[Department]
)
select * from cte_data,cte_data1
I was trying to measure the time between events with the exception of what one entry that has multiple processes between the start and end. I needed this in the context of other single line processes.
I used a select with an inner join as my select statement within the Nth cte. The second cte I needed to extract the start date on X and end date on Y and used 1 as an id value to left join to put them on a single line.
Works for me, hope this helps.
cte_extract
as
(
select ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'some_extract_tbl'
and convert(varchar(10), ProcessStartDate, 112) < '29991231'
) strt on strt.ProcessStatusId = ps.ProcessStatusID
),
cte_rls
as
(
select 'Sample' as ProcessEvent,
x.ProcessStartDate, y.ProcessEndDate from (
select 1 as Id, ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'XX Prcss'
and convert(varchar(10), ProcessStartDate, 112) < '29991231'
) strt on strt.ProcessStatusId = ps.ProcessStatusID
) x
left join (
select 1 as Id, ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'YY Prcss Cmpltd'
and convert(varchar(10), ProcessEndDate, 112) < '29991231'
) enddt on enddt.ProcessStatusId = ps.ProcessStatusID
) y on y.Id = x.Id
),
.... other ctes
Nested 'With' is not supported, but you can always use the second With as a subquery, for example:
WITH A AS (
--WITH B AS ( SELECT COUNT(1) AS _CT FROM C ) SELECT CASE _CT WHEN 1 THEN 1 ELSE 0 END FROM B --doesn't work
SELECT CASE WHEN count = 1 THEN 1 ELSE 0 END AS CT FROM (SELECT COUNT(1) AS count FROM dual)
union all
select 100 AS CT from dual
)
select CT FROM A