在查询参数中提供子查询

时间:2016-12-21 09:06:13

标签: postgresql elixir ecto

我需要使用Ecto实现以下查询,但它不会编译说子查询语句不是有效的表达式。

query = from p in Passphrase,
        left_join: pi in PassphraseInvalidation, on: p.id == pi.target_passphrase_id,
        join: u in User, on: p.user_id == u.id,
        where: p.passkey == ^passkey and
               is_nil(pi.inserted_at) and
               p.inserted_at > ago(5, "month") and
               p.inserted_at > subquery(from pr in PasswordReset,
                                        where: pr.user_id == u.id,
                                        select: max(pr.inserted_at)),
        select: {u, p}

user = Repo.one!(query)
  

(Ecto.Query.CompileError)子查询(来自(密码重置中的pr,其中:pr.user_id()== ^ u.id(),选择:max(pr.inserted_at())))不是有效的查询表达式。

等效的PgSQL查询类似于:

SELECT u.*, p.*
FROM passphrases p
LEFT OUTER JOIN passphrase_invalidations pi ON p.id = pi.target_passphrase_id
INNER JOIN users u ON p.user_id = u.id
WHERE p.passkey = '/* some passkey */' AND
      pi.inserted_at IS NULL AND
      u.id = 2 AND
      p.inserted_at > (SELECT max(pr.inserted_at)
                       FROM password_resets pr
                       WHERE pr.user_id = u.id)

有没有办法实现,或者我错过了什么?

2 个答案:

答案 0 :(得分:2)

从Ecto 2.1.0开始,根据https://hexdocs.pm/ecto/Ecto.Query.html#subquery/1,子查询无法在from中使用:

  

目前仅joinfragment字段支持子查询。

您现在可以使用p.inserted_at > fragment("(SELECT max(pr.inserted_at) FROM password_resets pr WHERE pr.user_id = u.id)") 并将整个子查询放入其中:

{{1}}

答案 1 :(得分:1)