sqlsql-servertreehierarchical-datahierarchyid

Get Lowest level in tree created with hierarchyId that respect some conditions


I have created a hierarchy table in my SQL Server. I have a column hierarchyId. Each level of hierarchy represent a geographical/political level of a country:

For each row I can fill some boundaries or not. To simplify I replace in the example the geometry column with a bit column.

I need to get lowest level that has boundaries filled. If at least one child has boundaries, surely also parent has boundaries.

I make an example:

enter image description here

For example, I have that tree. In my query I should get green and red areas. In this moment I get only green areas.. so, I should get:

My query is partially correct.. I get all lowest levels. But I do not get the minimum high level that respect my condition..

I share a link with the example: http://sqlfiddle.com/#!18/878577/1

Here also the query you can see in sql fiddler:

select * from country_subdivisions cs
   where IsoCode IN(
        select cs.IsoCode
          from parent p
         where cs.Level.IsDescendantOf(p.Level) = 1
           and p.CountryISOAlpha2Code = cs.CountryISOAlpha2Code
        --   and (cs.Level.GetLevel() = p.Level.GetLevel() + 1 or cs.Level.GetLevel() = p.Level.GetLevel())
            and cs.Level.GetLevel() = (SELECT MAX(leaf.Level.GetLevel()) FROM country_subdivisions leaf WHERE leaf.Level.IsDescendantOf(cs.Level) = 1 and leaf.HasBoundaries = 1)
           )

As you can see I correctly get the green areas but not the red one.

Any Idea? Do I have been clear?

Thank you


Solution

  • I think the logic is summarized as follows:

    Return a parent when:

    This could be formulated as follows:

    select parent.*
    from   country_subdivisions parent
    where  parent.HasBoundaries = 1
    and    0 < (select case 
                       when  count(*) = 0 then 1
                       else  count(case when child.HasBoundaries = 0 then 1 end)
                       end
                from   country_subdivisions child
                where  child.Level.GetAncestor(1) = parent.Level
               );