HiveBrain v1.2.0
Get Started
← Back to all entries
debugsqlMinor

CTE query that fails to find ancestors

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
failsancestorsqueryctethatfind

Problem

I have a table foo

with the content

So the records of the table foo can graphically be represented with this graph.

When I run a procedure that should return ancestors using @starting_id=9

(represented with a circle in the graph), I get this result

  • 9



instead of

  • 9



  • 3 and



  • 1



Why?

CREATE PROCEDURE [dbo].[GetParents]
    @starting_id int
AS
BEGIN
    WITH chainIDsUpwards AS
    (
        SELECT id, parent_id FROM foo WHERE id = @starting_id

        UNION ALL

        SELECT foo.id, foo.parent_id FROM foo
        JOIN chainIDsUpwards p ON p.id = foo.parent_id
    )

    SELECT id FROM chainIDsUpwards
END


Fiddle at https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=81be3d86dc7581eb60bc7af4c09077e4

Solution

I believe you made a mistake in your join predicate. Try:

WITH chainIDsUpwards AS
    (
        SELECT id, parent_id FROM foo WHERE id = @starting_id

        UNION ALL

        SELECT foo.id, foo.parent_id FROM foo
        JOIN chainIDsUpwards p ON p.parent_id = foo.id
    )

    SELECT id FROM chainIDsUpwards


It is a common mistake, and I often do it myself. I find it easiest to get it right if I start with the CTE:

SELECT foo.id, foo.parent_id 
    FROM chainIDsUpwards p
    JOIN foo p


and then think of the CTE as a linked list where I need to find the next element:

ON p.parent_id = foo.id

Code Snippets

WITH chainIDsUpwards AS
    (
        SELECT id, parent_id FROM foo WHERE id = @starting_id

        UNION ALL

        SELECT foo.id, foo.parent_id FROM foo
        JOIN chainIDsUpwards p ON p.parent_id = foo.id
    )

    SELECT id FROM chainIDsUpwards
SELECT foo.id, foo.parent_id 
    FROM chainIDsUpwards p
    JOIN foo p
ON p.parent_id = foo.id

Context

StackExchange Database Administrators Q#274233, answer score: 6

Revisions (0)

No revisions yet.