Answers.Body: <p>A bit late, but I've just come across this very problem and found a solution that works well enough. Thought I'd post it here in case anyone is trying to do something similar.</p>
  <hr />
  <p>As far as I can tell, doing this in the database query itself (without too many complicated custom selects / conditions) is not feasible. Category queries do have an option to <a href="https://craftcms.com/docs/3.x/categories.html#leaves" rel="nofollow noreferrer">only return leaf nodes</a> (categories without a descendant), but that doesn't match the problem. After all, we do want to display categories that don't have leaf nodes if none of those leaves are selected.</p>
  <p>So the only solution I could find is to fetch all selected categories and then filter them. We want to filter out all categories with descendants that are selected on this entry. We can take advantage of the fact that Craft automatically selects all ancestors of a term when a lower-level term is selected. Because of this, we know that for every category that we don't want to show, one other category in the list will have this category as it's <a href="https://docs.craftcms.com/api/v3/craft-base-element.html#parent" rel="nofollow noreferrer">parent</a>. So we can filter the list by checking for this condition:</p>
  <pre><code>{% set allSelectedCategories = entry.businessTypes.all() %}
  {% set leafNodesOnly = allSelectedCategories|filter(category =&gt;
      (allSelectedCategories|filter(
          c =&gt; c.parent is not empty and c.parent.id == category.id
      ) is empty)
  ) %}
  </code></pre>
  <p>The problem with that is that it has quadratic complexity since for every node, we're checking every node (the fact that Twig doesn't have something like <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some" rel="nofollow noreferrer">Array.prototype.some</a> doesn't help). If your entries have many categories, this may slow down the template considerably.</p>
  <hr />
  <p>We can also take advantage of the fact that category queries return their results in hierarchical order by default. So instead of checking if ANY category in the array is a child of the current one, we can just check the next category in the list. If it isn't a child of the current category, the current category in the loop is a leaf node.</p>
  <pre><code>{% set allSelectedCategories = entry.businessTypes.all() %}
  {% set leafNodesOnly = allSelectedCategories|filter((category, index) =&gt;
      allSelectedCategories[index + 1] is not defined or
      allSelectedCategories[index + 1].parent is empty or
      allSelectedCategories[index + 1].parent.id != category.id
  ) %}
  </code></pre>
  <p>However, this approach <strong>does not work if you've changed the sort order</strong> to anything other than the default.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-13T14:47:55.670Z
Answers.LastActivityDate: 2021-09-13T14:47:55.670Z
Answers.UserDisplayName: MoritzLost
Answers.Body: <p>I could not test it, but you could try:</p>
  
  <h2>If you always have a Parent and 2 levels</h2>
  
  <pre><code>entry.businessTypes.level('&gt;= 2').all()
  </code></pre>
  
  <h2>If you want to only get the lowest, you could try to assign it with a condition:</h2>
  
  <pre><code>{% if categories = entry.businessTypes.children %} 
      {% set categories = entry.businessTypes.level('&gt;= 2').all() %}
  {% else categories = entry.businessTypes.children %} 
      {% set categories = entry.businessTypes.all() %}
  {% endif %}
  
  {% for category in categories %} ... {% endfor %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-09T10:59:52.397Z
Answers.LastActivityDate: 2020-04-09T10:59:52.397Z
Answers.UserDisplayName: Max Strebel
Body: <p>I have a category tree like this and I have an entry that has four categories <strong>A, A1, B, C2</strong>:</p>
  
  <ul>
  <li>A
  
  <ul>
  <li>A1</li>
  <li>A2</li>
  </ul></li>
  <li>B
  
  <ul>
  <li>B1</li>
  <li>B2</li>
  </ul></li>
  <li>C
  
  <ul>
  <li>C1</li>
  <li>C2</li>
  </ul></li>
  </ul>
  
  <p>I want a query that ignores A and returns only A1, B, C2, because I don't want to display the parent category of a sub-category that's also displayed.</p>
  
  <p><code>{% for category in entry.businessTypes.all() %}{{ category.title }}{% endfor %}</code>
  returns all: A, A1, B, C2</p>
  
  <p><code>{% for category in entry.businessTypes.leaves().all() %}{{ category.title }}{% endfor %}</code>
  returns A2, C2 but not B.</p>
  
  <p><code>{% for category in entry.businessTypes.hasDescendants().all() %}{{ category.title }}{% endfor %}</code>
  returns A, B but not A1, C2.</p>
  
  <p>Any suggestions are appreciated.</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2021-02-09T13:40:38.667Z
Comments.Text: hey travis, did you find a solution for this problem?
Comments.UserDisplayName: Matthias Redl-Mann
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2021-09-13T14:49:34.680Z
Comments.Text: @MatthiasRedl-Mann I've just posted an answer with two working solutions, even though they do the filtering in memory instead of in the database query itself.
Comments.UserDisplayName: MoritzLost
Tags: <category><query>
Title: How can I display just the "lowest" categories assigned to an entry and not parent categories?
ThreadText: # How can I display just the "lowest" categories assigned to an entry and not parent categories?
  
  (Asked by: username_0 on 2020-04-08)
  
  I have a category tree like this and I have an entry that has four categories **A, A1, B, C2**:
  
  * A
    + A1
    + A2
  * B
    + B1
    + B2
  * C
    + C1
    + C2
  
  I want a query that ignores A and returns only A1, B, C2, because I don't want to display the parent category of a sub-category that's also displayed.
  
  `{% for category in entry.businessTypes.all() %}{{ category.title }}{% endfor %}`
  returns all: A, A1, B, C2
  
  `{% for category in entry.businessTypes.leaves().all() %}{{ category.title }}{% endfor %}`
  returns A2, C2 but not B.
  
  `{% for category in entry.businessTypes.hasDescendants().all() %}{{ category.title }}{% endfor %}`
  returns A, B but not A1, C2.
  
  Any suggestions are appreciated.
  
  **Tags:** category, query
  
  > **Comments:**
  > **username_1**: hey travis, did you find a solution for this problem?  
  > **username_2**: @username_1 I've just posted an answer with two working solutions, even though they do the filtering in memory instead of in the database query itself.  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2021-09-13. Score: 2
  
  A bit late, but I've just come across this very problem and found a solution that works well enough. Thought I'd post it here in case anyone is trying to do something similar.
  
  ---
  
  As far as I can tell, doing this in the database query itself (without too many complicated custom selects / conditions) is not feasible. Category queries do have an option to [only return leaf nodes](https://craftcms.com/docs/3.x/categories.html#leaves) (categories without a descendant), but that doesn't match the problem. After all, we do want to display categories that don't have leaf nodes if none of those leaves are selected.
  
  So the only solution I could find is to fetch all selected categories and then filter them. We want to filter out all categories with descendants that are selected on this entry. We can take advantage of the fact that Craft automatically selects all ancestors of a term when a lower-level term is selected. Because of this, we know that for every category that we don't want to show, one other category in the list will have this category as it's [parent](https://docs.craftcms.com/api/v3/craft-base-element.html#parent). So we can filter the list by checking for this condition:
  
  ```
  {% set allSelectedCategories = entry.businessTypes.all() %}
  {% set leafNodesOnly = allSelectedCategories|filter(category =>
      (allSelectedCategories|filter(
          c => c.parent is not empty and c.parent.id == category.id
      ) is empty)
  ) %}
  
  ```
  
  The problem with that is that it has quadratic complexity since for every node, we're checking every node (the fact that Twig doesn't have something like [Array.prototype.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) doesn't help). If your entries have many categories, this may slow down the template considerably.
  
  ---
  
  We can also take advantage of the fact that category queries return their results in hierarchical order by default. So instead of checking if ANY category in the array is a child of the current one, we can just check the next category in the list. If it isn't a child of the current category, the current category in the loop is a leaf node.
  
  ```
  {% set allSelectedCategories = entry.businessTypes.all() %}
  {% set leafNodesOnly = allSelectedCategories|filter((category, index) =>
      allSelectedCategories[index + 1] is not defined or
      allSelectedCategories[index + 1].parent is empty or
      allSelectedCategories[index + 1].parent.id != category.id
  ) %}
  
  ```
  
  However, this approach **does not work if you've changed the sort order** to anything other than the default.
  
  
  ---
  
  ### Answer by username_3 on 2020-04-09. Score: 1
  
  I could not test it, but you could try:
  
  ## If you always have a Parent and 2 levels
  
  ```
  entry.businessTypes.level('>= 2').all()
  
  ```
  
  ## If you want to only get the lowest, you could try to assign it with a condition:
  
  ```
  {% if categories = entry.businessTypes.children %} 
      {% set categories = entry.businessTypes.level('>= 2').all() %}
  {% else categories = entry.businessTypes.children %} 
      {% set categories = entry.businessTypes.all() %}
  {% endif %}
  
  {% for category in categories %} ... {% endfor %}
  
  ```
  
  
  ---
  
  