Search code examples
sqlsql-servercasebinary-search-treesql-server-2019

Return more than one int value


I have created a BST table with two integer columns Node and Parent. I insert some values into this table and I want to detect leaf,inner and root node.

Code:

CREATE TABLE BST 
(
    Node int,
    Parent int
);

INSERT INTO BST (Node, Parent) VALUES (1, 2);
INSERT INTO BST (Node, Parent) VALUES (3, 2);
INSERT INTO BST (Node, Parent) VALUES (6, 8);
INSERT INTO BST (Node, Parent) VALUES (9, 8);
INSERT INTO BST (Node, Parent) VALUES (2, 5);
INSERT INTO BST (Node, Parent) VALUES (8, 5);

INSERT INTO BST (Node) VALUES (5);

I write this query:

SELECT
    Node,
    CASE
        WHEN Parent IS NULL THEN 'Root'
        WHEN Node IS NOT NULL AND Parent IS NOT NULL
             AND (SELECT Node FROM BST) NOT IN (SELECT Parent FROM BST) 
            THEN ('Leaf')
        WHEN Node IS NOT NULL AND Parent IS NOT NULL
             AND (SELECT Parent FROM BST) NOT IN (SELECT Node FROM BST)
            THEN ('Inner')
    END
FROM
    BST;

And I was expecting to get a result like this:

1 Leaf
2 Inner 
3 Leaf
5 Root
6 Leaf
8 Inner
9 Leaf

But I get this error:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Does anyone have any idea about this problem. Is this a syntax error or logical error? or my algorithm is not right...


Solution

  • As with my comment, this table design is poor for a BST. But it's not impossible, and we can get the desired answer (without needing a formal full traversal!) by using a lateral join from the table to itself:

    SELECT p.Node, CASE WHEN p.Parent IS NULL THEN 'Root'
                        WHEN fc.Node IS NULL THEN 'Leaf'
                        ELSE 'Inner' END As NodeType
    FROM BST p -- parent
    OUTER APPLY (SELECT TOP 1 c.Node FROM BST c WHERE c.Parent = p.Node) fc -- first child
    ORDER BY p.Node
    

    It should also be possible to do this using a correlated subquery (and NOT EXISTS()) in the SELECT clause, but I find this much easier to write and reason about.

    See it work here:

    https://dbfiddle.uk/wNFbOdl4