Clojure 如何将HoneySQL句柄order by作为复合键?

Clojure 如何将HoneySQL句柄order by作为复合键?,clojure,honeysql,Clojure,Honeysql,请注意,输出已经“样式化”,因此在这里的阅读效果更好 我所拥有的 (sql/format (-> (sqlh/select :*) (sqlh/from :event) (sqlh/merge-where [:in :field_id ["1673576", "1945627", "1338971"]]) (sqlh/merge-where [:in :layer ["fha.abs" "fha.rank" "fha.true-color"]]

请注意,输出已经“样式化”,因此在这里的阅读效果更好

我所拥有的

(sql/format 
  (-> 
    (sqlh/select :*) 
    (sqlh/from :event) 
    (sqlh/merge-where [:in :field_id ["1673576", "1945627", "1338971"]]) 
    (sqlh/merge-where [:in :layer ["fha.abs" "fha.rank" "fha.true-color"]])
    (sqlh/merge-order-by :field_id)
    (sqlh/merge-order-by :layer)
    (sqlh/merge-order-by :event_date)
    (sqlh/limit 5)))
=>
["SELECT * 
  FROM event 
  WHERE ((field_id in (?, ?, ?)) AND (layer in (?, ?, ?))) 
  ORDER BY field_id, layer, event_date 
  LIMIT ?"
 "1673576"
 "1945627"
 "1338971"
 "fha.abs"
 "fha.rank"
 "fha.true-color"
 5]
我想要的

(sql/format 
  (-> 
    (sqlh/select :*) 
    (sqlh/from :event) 
    (sqlh/merge-where [:in :field_id ["1673576", "1945627", "1338971"]]) 
    (sqlh/merge-where [:in :layer ["fha.abs" "fha.rank" "fha.true-color"]])
    ;;; this doesn't work, but is conceptually what I'm looking for
    (sqlh/merge-order-by [:field_id :layer :event_date])
    (sqlh/limit 5)))
=>
["SELECT * 
  FROM event 
  WHERE ((field_id in (?, ?, ?)) AND (layer in (?, ?, ?))) 
  ORDER BY (field_id, layer, event_date) 
  LIMIT ?"
 "1673576"
 "1945627"
 "1338971"
 "fha.abs"
 "fha.rank"
 "fha.true-color"
 5]
如何让HoneySQL发出将ORDERBY子句视为表本身用作主键的复合键的SQL

似乎HoneySQL应该能够做到这一点,因为当在where子句中遇到相同的挑战时,它“做了正确的事情”,如

(sql/format
  (->
    (sqlh/select :*)
    (sqlh/from :event)
    (sqlh/merge-where [:= [:field_id :layer :event_date] ["1338971" "fha.abs" (c/from-string "2011-08-02T10:54:55-07")]])))
=>
["SELECT * FROM event WHERE (field_id, layer, event_date) = (?, ?, ?)"
 "1338971"
 "fha.abs"
 #object[org.joda.time.DateTime 0xe59f807 "2011-08-02T17:54:55.000Z"]]

首先,您需要查看
orderby

(sql/format {:order-by [:c1 :c2]}) 
=> ["ORDER BY c1, c2"]
(sql/format {:order-by [[:c1 :desc] :c2]})
=> ["ORDER BY c1 DESC, c2"]
这是关于生成顺序的结构

如果查看宏
deffhelper
,它将完成两件事

  • 为等级库类型定义记录
  • 定义一个函数来调用该方法
  • 
    (做
    (定义方法)
    构建子句
    :订购人
    [m字段]
    (关联m:排序依据(合并字段)))
    (由[&args_uu14903_uu_uauto_uu_u]定义订单)
    (设[[m__14904____自动____参数___14903___自动__](如果
    (普通地图?
    (一)
    参数(14903自动)
    [(首先
    参数(14903自动)
    (其余
    args_uuu14903_uuuauto_uuuu)]
    [{}
    args_uuu14903_uuuuauto_uuuuuu])]
    (构建条款:由m_uuu14904_uuuauto_uuuargs_uuu14903_uauto_uuu)订购)
    (alter meta!#“按关联顺序:arglist”([fields][m fields]))
    

    collify
    非常简单

     (defn collify [x]
         (if (coll? x) x [x]))
    
    因此,我们需要看看
    defn order by
    函数。 当您调用
    (sqlh/merge order by{}[:a:b])

    args_uu14903_uuauto_uu=”({}[:a:b])

    第一个
    if
    将创建两个var
    m_uu14904_uuauto_uu={}
    args_u14903_uauto_uu=(rest args_u14903_uauto_u)=([:a:b])

    所以,我猜函数的合并顺序是错误的

    我这样解决你的问题

    (sql/format
      (->
        (sqlh/select :*)
        (sqlh/from :event)
        (sqlh/merge-where [:in :field_id ["1673576", "1945627", "1338971"]])
        (sqlh/merge-where [:in :layer ["fha.abs" "fha.rank" "fha.true-color"]])
        (sqlh/merge-order-by [:field_id :desc] :layer :event_date)
        (sqlh/limit 5)))
    

    已经两年多了,但我终于了解了足够多的Clojure,并且与HoneySQL合作了足够长的时间,看到了我年轻的自己缺失了什么。它不希望复合键作为向量:
    sqlh/order by
    是可变的:

    (doc sqlh/order-by)
    -------------------------
    honeysql.helpers/order-by
    ([& fields] [m & fields])
      nil
    
    它真正想要的是
    (sqlh/orderby:field\u id:layer[:event\u date:desc])
    。向量仅用于生成特定字段排序描述

    这就是我想做的:

    (-> (sqlh/select :*)
        (sqlh/from :event)
        (sqlh/merge-where [:in :field_id field-ids])
        (sqlh/merge-where (cond (not-empty layers) [:in :layer layers]))
        (sqlh/merge-where (make-where-for-timestamp
                            :event_date event-date-from event-date-to))
        (sqlh/merge-where (make-where-for-timestamp
                            :updated_at updated-at-from updated-at-to))
        (sqlh/order-by :field_id :layer [:event_date :desc])
        sql/format)
    =>
    ["SELECT * FROM event WHERE ((field_id in (?)) AND (layer in (?, ?, ?))) ORDER BY field_id, layer, event_date DESC"
     "1325629"
     "fha.true-color"
     "fha.abs"
     "fha.rank"]
    

    @救世主始终是正确的。我的Clojure不够好,无法理解它。

    生成的第二个查询与第一个查询有何不同?@AshishNegi在第二个查询中,order by子句位于元组上,而不是3个单独的字段上。最终,这将允许我在一条语句中反转排序顺序。是的,但不是两条语句都给出相同的结果?。。不管你有元组还是单个字段。@AshishNegi它给出了相同的初始结果,这是正确的,但当我展望我试图用它做什么时;实现一个只需要限制而不需要偏移的分页解决方案,我需要能够将这3个不同的字段作为一个单元来处理。HoneySQL在where子句中做了正确的事情(我将此添加到问题中),我正在寻找order-by中的等效行为。可能您应该尝试提出真正的问题,关于限制/偏移以及如何使用order-by,它们在使用/不使用元组的情况下给出不同的结果。不完全正确,但做得很好。我越是关注这一点,就越觉得HoneySQL助手无法做到这一点,但也许这并不重要。当我查看PostgreSQL对实际查询的解释时,它对ORDER BY(字段id、图层、事件日期)DESC和vs(ORDER BY字段id DESC、图层DESC、事件日期DESC)没有问题;它似乎产生了相同的查询计划……我不得不如此细粒度地执行这一操作,这让我感到很不舒服,因为helper类实际上并没有直接映射到底层SQL