如何通过复合键使HoneySQL处理顺序?

时间:2016-10-30 22:01:43

标签: clojure honeysql

请注意,输出已经“风格化”,因此在SO上可以更好地阅读。

我得到了什么......

(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发出将我的order by子句视为表本身用作主键的复合键的SQL?

似乎HoneySQL应该能够做到这一点,因为它在像where ...这样的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"]]

2 个答案:

答案 0 :(得分:3)

首先,您需要查看order-by

上的格式行为
(sql/format {:order-by [:c1 :c2]}) 
=> ["ORDER BY c1, c2"]
(sql/format {:order-by [[:c1 :desc] :c2]})
=> ["ORDER BY c1 DESC, c2"]

这是关于将要生成的order-by的结构。

如果你看一下宏defhelper,它会做两件事。

  1. 规范类型的defrecord
  2. 定义一个调用mutimethod的函数
  3. (do (defmethod build-clause :order-by [_ m fields] (assoc m :order-by (collify fields))) (defn order-by [& args__14903__auto__] (let [[m__14904__auto__ args__14903__auto__] (if (plain-map? (first args__14903__auto__)) [(first args__14903__auto__) (rest args__14903__auto__)] [{} args__14903__auto__])] (build-clause :order-by m__14904__auto__ args__14903__auto__))) (alter-meta! #'order-by assoc :arglists '([fields] [m fields])))

    collify非常简单。

     (defn collify [x]
         (if (coll? x) x [x]))
    

    因此,我们需要查看defn order-by函数。 致电(sqlh/merge-order-by {} [:a :b])时,

    args__14903__auto__ = '({} [:a :b])

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

    所以,我认为merge-order-by函数是错误的。

    我这样解决你的问题。

    (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)))
    

答案 1 :(得分:1)

已经2年多了,但是我终于对Clojure有了足够的了解,并且与HoneySQL一起工作了足够长的时间,以了解年轻的自我所缺少的东西。它不希望将复合键用作向量:class Project(models.Model): project_name = models.CharField(max_length=200,unique=True) project_scan = models.IntegerField() ### Scan interval project_status = models.BooleanField() ### To Enable "Scan" or Disable "Scan" Tasks schedule = IntervalSchedule() 是可变的:

sqlh/order-by

它真正想要的是(doc sqlh/order-by) ------------------------- honeysql.helpers/order-by ([& fields] [m & fields]) nil 。仅需对向量进行特定字段排序DESC。

这就是我想要做的:

(sqlh/order-by :field_id :layer [:event_date :desc])

@savior一直是https://stackoverflow.com/a/40356529/688355正确的。我的Clojure不够好,无法理解。