honeysql

igrishaev 2024-05-10T15:05:58.993079Z

Is there a way to compose the following ORDER BY clause?

select ... order by 1
Above, 1 is the number of a column. This approached is used in Postgres within the union operator:
select ... union select ... order by 1 (the first column)
I've been trying {:order-by 1}, {:order-by [:raw "1"]} , etc, but none of these gave me the right result.

igrishaev 2024-05-10T15:07:54.263539Z

ha, it was simple:

(honey.sql/format {:select [:foo] :order-by [:1]})

["SELECT foo ORDER BY 1 ASC"]
yet took some time to figure out

p-himik 2024-05-10T15:08:36.741509Z

I'd use [:inline 1].

igrishaev 2024-05-10T15:09:18.819699Z

it won't work:

(honey.sql/format {:select [:foo] :order-by [:inline 1]})

["SELECT foo ORDER BY inline ASC, ? ASC" 1]

p-himik 2024-05-10T15:09:43.473229Z

Just as with other functions and specials (so, also true for :raw), you gotta wrap it:

(sql/format {:select :x 
             :from :t 
             :order-by [[[:raw "1"]]]})
=> ["SELECT x FROM t ORDER BY 1 ASC"]

igrishaev 2024-05-10T15:11:07.690649Z

right, and I didn't try 3-level expression.

igrishaev 2024-05-10T15:11:26.364339Z

I've been trying only [] and [[]]

p-himik 2024-05-10T15:11:47.991789Z

... - an item. [...] - a collection with one item. [[...]] - a collection with one item with some space for parameters (aliases for :select, direction for :order). [[[...]]] - the innermost collection is the item, with no parameters.

igrishaev 2024-05-10T15:12:20.517519Z

yeah I use them in select and from, but never with order-by. Thanks!

👍 1
José Javier Blanco Rivero 2024-05-10T15:13:58.988129Z

And how would you treat the order by in this case? SELECT * FROM items ORDER BY embedding <=> '[...]' This is from PostgresSQL using the extension pgvector

p-himik 2024-05-10T15:15:46.477129Z

<=> is not known by HoneySQL as an infix operator, so you gotta register it first:

(sql/register-op! :<=>)
=> nil
(sql/format {:select :* 
             :from :items 
             :order-by [[[:<=> :embedding [:inline "[...]"]]]]})
=> ["SELECT * FROM items ORDER BY embedding <=> '[...]' ASC"]

👍 1
igrishaev 2024-05-10T15:16:31.344139Z

Sorry I didn't get it. In your query, you use a custom expression which gets executed for each row, and then the database sorts the rows by the values.

igrishaev 2024-05-10T15:17:44.287389Z

But if you want to sort the result of UNION, you don't have the names of the columns but only their numbers. So, order by 1 will sort the whole union result by the first column, which is usually some kind of score/rank

igrishaev 2024-05-10T15:19:08.304209Z

IN your case, it will be something like that:

{:order-by [:<=> :some-field some-value]}

p-himik 2024-05-10T15:19:27.502149Z

It will fail, because of a single vector. :) See my example above.

igrishaev 2024-05-10T15:19:41.984179Z

ah, again 🙂