Подзапросы с функцией выбора в CLSQL
Я пытаюсь создать подзапрос с помощью функции clsql:select:
CL-USER> (select [books.bookid]
:from [books]
:where
(sql-in [books.bookid]
(select [bookid]
:from [bookauthors]
:where
(sql-= [bookauthors.authorid] 120))))
;; 2015-03-07T06:37:08 /books/ => SELECT BOOKID FROM BOOKAUTHORS WHERE (BOOKAUTHORS.AUTHORID = 120)
;; 2015-03-07T06:37:08 /books/ => SELECT BOOKS.BOOKID FROM BOOKS WHERE (BOOKS.BOOKID IN ((157)))
((157))
("bookid")
Это работает, но вместо генерации одного запроса с предложением sub-select clsql выполняет два запроса. Это не так эффективно, как позволить бэкенду postgresql обрабатывать все это.
CL-USER> (clsql-sys:db-type-has-subqueries? :postgresql)
T
Очевидно, коннектор postgresql поддерживает подзапросы. Есть ли способ получить функцию выбора для их генерации?
1 ответ
В ваших предыдущих вызовах вы фактически выполняете внутренний выбор, а затем объединяете результаты во внешний вызов.
Вы должны использовать sql-выражения вместо функций. если ты (clsql-sys:file-enable-sql-reader-syntax)
это можно сделать с помощью квадратных скобок следующим образом.
(select [books.bookid]
:from [books]
:where
[in [books.bookid]
[select [bookid]
:from [bookauthors]
:where
[= [bookauthors.authorid] 120]]))
Кроме того, вы можете использовать :postgresql-socket3
бэкэнд, поскольку он является самым надежным / самым последним из трех бэкэндов postgresql clsql (он использует cl-postgresql
библиотека предоставлена postmodern
чтобы получить доступ к postgresql через версию 3 его сокета API. :posgresql-socket
использует версию 2 сокета postgres api, и :postgres
использует FFI через клиент C