Subquery 亦為常用 SQL 語法,不過在 Knex 文件並沒有說明,因此特別紀錄之。
Version
Knex 0.20.2
Knex-fp 0.0.11
SQL
SELECT title, price,
(SELECT name
FROM categories
WHERE books.categoryId = categories.id) as category
FROM books
有些時候我們會使用 subquery 取得 field 資料。
Knex
import { log } from 'wink-fp'
let categoryId = mySQL.ref ('books.categoryId')
let category =
mySQL ('categories')
.select ('name')
.where ('id', categoryId)
.as ('category')
mySQL ('books')
.select ('title', 'price', category)
.then (log)
第 3 行
let categoryId = mySQL.ref ('books.categoryId')
使用 mySQL.ref
將主 table 的 field 取別名。
第 5 行
let category =
mySQL ('categories')
.select ('name')
.where ('id', categoryId)
.as ('category')
另外建立 category
,最後以 as
取 field 別名。
11 行
mySQL ('books')
.select ('title', 'price', category)
.then (log)
將 category
放在 select
的 argument 中。
import { log } from 'wink-fp'
mySQL ('books')
.select('title', 'price', mySQL('categories')
.select ('name')
.where ('id', mySQL.ref('books.categoryId'))
.as ('category'))
.then(log)
若不想建立 category
與 categroyId
,寫在一起可讀性也不差。
Knex-fp
import { pipe } from 'ramda'
import { ref, select, where, as, pipeK } from 'knex-fp'
import { log } from 'wink-fp'
let categoryId = ref ('books.categoryId') (mySQL)
let category = pipe (
select ('name'),
where ('id', categoryId),
as ('category')
) (mySQL('categories'))
pipeK (
select ('title', 'price', category)
) (log) (mySQL('books'))
第 5 行
let categoryId = ref ('books.categoryId') (mySQL)
改由 Knex-fp 的 ref
產生 categoryId
。
第 7 行
let category = pipe (
select ('name'),
where ('id', categoryId),
as ('category')
) (mySQL('categories'))
改由 as
產生 category
。
13 行
pipeK (
select ('title', 'price', category)
) (log) (mySQL('books'))
由 pipeK
組合 Knex 的 select
與 Wink-fp 的 log
。
import { pipe } from 'ramda'
import { ref, select, where, as, pipeK } from 'knex-fp'
import { log } from 'wink-fp'
pipeK (
select ('title', 'price', pipe (
select ('name'),
where ('id', ref ('books.categoryId') (mySQL)),
as ('category')
)(mySQL ('categories')))
) (log) (mySQL('books'))
若不想建立 category
與 categroyId
,也可通通寫在 pipeK
內,可讀性亦佳。
Conclusion
- 大部分 subquery 都可使用 join 取代,若真的要使用 subquery,可參考本文方式