點燈坊

失くすものさえない今が強くなるチャンスよ

如何將 OR 寫在 () 內 ?

Sam Xiao's Avatar 2021-10-22

實務上有時 OR 條件並不是與 AND 同一層,而是躲在 () 內,這種特殊 SQL 在 Knex 該如何寫呢 ?

Version

Knex 0.20.2
Knex-fp 0.0.8

SQL

SELECT title, price
FROM books
WHERE title LIKE '%JavaScript%'
  AND (price = 100 or price = 200)

有時候 or 會在 () 括號內,外面才接 and

or000

Knex

import { format, log } from 'wink-fp'

mySQL ('books')
  .select ('title', 'price')
  .where ('title', 'like', '%JavaScript%')
  .andWhere (x =>
    x.where ('price', 100)
     .orWhere ('price', 200)
  )
  .then (map (format('{title}: {price}')))
  .then (log)

最外層的 and 使用 andWhere 不訝異,()or 則要以 callback 形式,在 arrow function 內接 whereorWhere

Knex-fp

import { select, where, andWhere, orWhere, pipeK } from 'knex-fp'
import { pipe, map } from 'ramda'
import { format, log } from 'wink-fp'

pipeK (
  select ('title', 'price'),
  where ('title', 'like', '%JavaScript%'),
  andWhere (pipe (
    where ('price', 100),
    orWhere ('price', 200)
  ))
)(
  map (format ('{title}: {price}')),
  log
) (mySQL ('books'))

也可使用 Knex-fp 的 pipeK 一次組合 Knex function 與 Ramda, Wink-fp function。

至於 andWhere 的 callback,也可使用 pipewhereorWhere 組合起來使其 Point-free。

or001

Conclusion

  • Knex 很多進階寫法都使用 callback,當複雜 SQL 不知道怎麼寫時,朝 callback 去找資料準備錯
  • 亦可使用 Knex-fp 以 Function Pipeline 完成需求