在 knex 查询中使用 postgres 函数 "arr agg" 时出错

Error using postgres function "arr agg" in a knex query

我在尝试 运行 以下查询时遇到了问题 运行。我得到

missing FROM-clause entry for table \"s\"".

我这里有四个 table:grantsusersregionsstates

我正在尝试获取一个嵌套的 "state" 对象,这样当在多个州提供赠款时我就不会得到重复的记录。区域 table 是 innerJoin 因为总会有一个值与赠款 table 相匹配:"state_wide" 是一个布尔值。

return db("grants as G")
  .innerJoin("users AS U", "G.user_id", "U.id")
  .innerJoin("regions AS R", "G.id", "R.grant_id")
  .leftJoin("states AS S", "R.state_id", "=", "S.id")
  .select(
    "G.id",
    "G.grant_title",
    "G.grant_number",
    "G.grant_status",
    "G.grant_description",
    "G.grant_amount",
    "G.due_date",
    "U.first_name",
    "U.last_name",
    "U.email",
    "U.telephone",
    "U.department",
    "U.organization_name",
    "U.address_one",
    "U.address_two",
    "U.zip_code",
    "R.country_wide",
    "R.state_id",
    "R.county_id",
    db.raw("array_agg(S.state_name) AS state")
  )
  .groupBy("G.id", "G.grant_title");

整个错误消息

    "Message": "There was an error with your request",
    "Error": "select \"G\".\"id\", \"G\".\"grant_title\", \"G\".\"grant_number\", \"G\".\"grant_status\", \"G\".\"grant_description\", \"G\".\"grant_amount\", \"G\".\"due_date\", \"U\".\"first_name\", \"U\".\"last_name\", \"U\".\"email\", \"U\".\"telephone\", \"U\".\"department\", \"U\".\"organization_name\", \"U\".\"address_one\", \"U\".\"address_two\", \"U\".\"zip_code\", \"R\".\"country_wide\", \"R\".\"state_id\", \"R\".\"county_id\", ARRAY_AGG(S.state_name) as state from \"grants\" as \"G\" inner join \"users\" as \"U\" on \"G\".\"user_id\" = \"U\".\"id\" inner join \"regions\" as \"R\" on \"G\".\"id\" = \"R\".\"grant_id\" left join \"states\" as \"S\" on \"R\".\"state_id\" = \"S\".\"id\" - missing FROM-clause entry for table \"s\""
}```

啊哈。我花了一段时间,但问题是(正如 richyen 暗示的那样)您使用的是大写别名。正如我在评论中指出的那样,错误使用小写 's'.

感觉很奇怪

Postgres is case-insensitive when it comes to keywords and unquoted identifiers.

通常,Knex 用双引号将您的 table 名称括起来,正如您在错误消息中看到的那样,因此区分大小写。但是,它不能将 knex.raw 语句中的别名括起来,因为对于 Knex 来说它只是一个字符串。这导致 Postgres 去寻找 s.state_name,它确实缺少 FROM 子句。

因此您需要自己引用它:

db.raw('array_agg("S".state_name) AS state')

或者(更简单)养成始终使用小写别名的习惯!