Fork me on GitHub
#xtdb
<
2021-07-21
>
Samuel McHugh13:07:01

Hi all, I had a question about Q2 from the aggregates section https://nextjournal.com/try/learn-crux-datalog-today/learn-crux-datalog-today#aggregates. Particularly about adapting the following solution

(q '{:find [(min date)]
     :where [[_ :person/born date]]})
This returns the birthdate of the oldest person in our dataset. The question is, can the query be adapted to also return the name of this person. My naive idea was to do something like
(q '{:find [name (min date)]
     :where [[_ :person/born date]
             [_ :person/name name]]})
however this doesn't work because it will return a set of items where each item is the name of a different person. So how can we couple the name to refer to the data coming from the aggregator. Can we only achieve this with 2 queries? Maybe we can only achieve this by also providing some relational list in the arguments?

refset16:07:35

Hi, good question! I think you're right that 2 queries is the answer, but using subqueries you can still treat it as one query:

(q '{:find [name date]
     :where [[(q '{:find [(min date)]
                   :where [[_ :person/born date]]}) [[date]]]
             [p :person/born date]
             [p :person/name name]]})
(note, I've not attempted to actually run this yet...) That query may still return multiple names though, since multiple persons can share the same birth date, so you might want to also do an :order-by [[name :asc]] and :limit 1 if you are looking for a single deterministic result For a more complex example of subqueries see here https://github.com/juxt/crux/blob/6d602bb5b6caed199f10fd8c3711cb034d49248a/crux-test/src/crux/fixtures/tpch.clj#L285-L317 🙂

Samuel McHugh18:07:21

I checked and your solution did work. Thanks!

🙌 2