Query to list task by priority & scheduled/deadline in the near future

I’m trying to create a query where I can list all TODO/LATER from a specific priority (including items that have a Deadline/Schedule. However, I want to filter out Deadline/Scheduled tasks that are too far in the future (for example, only list Deadline/Scheduled for the next 7 days). Overdue Deadline/Scheduled are fine, but I have some tasks for next year that I don’t want to have listed. Also, I’d like to sort the Deadline/Scheduled tasks above the Unscheduled ones and organize them from further overdue up to 7 days in the future.

So far, I’ve come up with this:

#+BEGIN_QUERY 
{:title [:h3 "Priorities (advanced)"]
  :query [:find (pull ?b [*])
    :in $ ?end
      :where
        [?b :block/priority "C"]
          (or
            [?b :block/marker "TODO"]
            [?b :block/marker "LATER"]
          )
          (or
            (not [?b :block/deadline _ ]) ;; To include all tasks that DON'T have a deadline
            [?b :block/deadline  _] ;; To include all the tasks with a deadline, but I haven't filtered it.
          )
  ]
  :result-transform (fn [result]
    (sort-by (fn [b]
      (or (get b :block/scheduled) (get b :block/deadline))) result)) ;; NO idea how to sort things, I copied this
  :inputs [:+7d]
  :table-view? false
  :breadcrumb-show? false
  :collapsed? false
}
#+END_QUERY

Could anybody please help me out? I’m also trying to understand the language better, but it’s a bit weird to me.

I’ve made some tweaks and added some comments. Let me know if you have any questions :smiley:
Hopefully this is what you were looking for.

#+BEGIN_QUERY
{:title [:h3 "Priorities (advanced)"]
 :inputs [:+7d]
 :query [:find (pull ?b [*])
  :in $ ?end
   :where
    [?b :block/priority "C"]
    (or
      [?b :block/marker "TODO"]
      [?b :block/marker "LATER"]
    )
    (or-join [?b ?end] ; We only need ?b and ?end to be bound to the rest of the query. We can't have and not have a deadline at the same time unless we do it this way.
      (not [?b :block/deadline]) ; A task doesn't have a deadline
      (and ;Or it does have a deadline no more than 7 days in the future
        [?b :block/deadline ?d] ; a deadline of ?d
        [(<= ?d ?end)] ; which is smaller or equal to ?end
      )
    )
 ]
 :result-transform (fn [result] 
  (sort-by 
    (min ;changed this to min as I couldn't get the or to work with the replacement value of 99999999
      (fn [d] (get d :block/scheduled 99999999) ) ; when a task doesn't have this, use 99999999 to make it appear at the bottom.
      (fn [d] (get d :block/deadline 99999999) ) 
    )
    result
   )
 )
 :breadcrumb-show? false
}
#+END_QUERY

1 Like

Thank you! This is absolutely what I needed! I really appreciate the comments to figure out the code.

I extended it a bit to include scheduled tasks, could you please check it out?

#+BEGIN_QUERY
{:title [:h3 "Priorities (advanced)"]
 :inputs [:+7d]
 :query [:find (pull ?b [*])
  :in $ ?end
   :where
    [?b :block/priority "A"]
    (or
      [?b :block/marker "TODO"]
      [?b :block/marker "LATER"]
    )
    (or-join [?b ?end]
      (not [?b :block/deadline])
      (and
        [?b :block/deadline ?d]
        [(<= ?d ?end)]
      )
    )
    (or-join [?b ?end]
      (not [?b :block/scheduled])
      (and
        [?b :block/scheduled ?d]
        [(<= ?d ?end)]
      )
    )
 ]
 :result-transform (fn [result] 
  (sort-by 
    (min
      (fn [d] (get d :block/scheduled 99999999) )
      (fn [d] (get d :block/deadline 99999999) ) 
    )
    result
   )
 )
 :breadcrumb-show? false
 :group-by-page? false
 :collapsed? false
}
#+END_QUERY

I am, however, having trouble making one where there are NO priorities. I surrounded the first clause with a “not()”, but it’s telling me I have insufficient bindings? Is the NOT clause changing the scope?

Here’s the code:

#+BEGIN_QUERY
{:title [:h3 "No priorities"]
 :inputs [:+7d]
 :query [:find (pull ?b [*])
  :in $ ?end
   :where
    (not [?b :block/priority])
    (or
      [?b :block/marker "TODO"]
      [?b :block/marker "LATER"]
    )
    (or-join [?b ?end]
      (not [?b :block/deadline])
      (and
        [?b :block/deadline ?d]
        [(<= ?d ?end)]
      )
    )
    (or-join [?b ?end]
      (not [?b :block/scheduled])
      (and
        [?b :block/scheduled ?d]
        [(<= ?d ?end)]
      )
    )
 ]
 :result-transform (fn [result] 
  (sort-by 
    (min
      (fn [d] (get d :block/scheduled 99999999) )
      (fn [d] (get d :block/deadline 99999999) ) 
    )
    result
   )
 )
 :breadcrumb-show? false
 :group-by-page? false
 :collapsed? false
}
#+END_QUERY

Looks good! This query now states, the task has to have either no deadline or a deadline within range AND no scheduled or a scheduled within range.
So a task with a deadline within range and a scheduled date outside of it won’t show up. (haven’t tested, but that’s my idea of it). Not sure if this is your intention or not.
You can also make it one big or statement so that any of the arguments needs to be true. Up to you :slight_smile:

We cannot exclude that which we haven’t defined yet.
A not clause will make a selection that the query then tries to subtract that from the existing result. However we don’t have a result just yet.
Just move that statement after the or clause for the block marker and it’ll work.

1 Like