微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Ecto.Query 进行递归 SQL 查询

如何解决使用 Ecto.Query 进行递归 SQL 查询

我有一个包含以下列的 categories 表:

id
name
parent_id (nullable)

还有一个 books 表,里面有一个 category_id 列。 我想要一个函数,它接受一个类别 id 列表 (category_ids) 并返回一个查询,该查询获取属于给定类别之一或其子项(递归)的书籍。

我已经编写了一个查询,该查询返回给定类别的所有子项。我可以使用它来获取 category_ids 类别的所有子类别并使用新列表。但它会向数据库发送几个查询,我想在一个查询中完成。这是查询

with recursive cat_tree as (
  select id,name,parent_id
  from categories
  where id = $1
  union all
  select child.id,child.name,child.parent_id
  from categories as child
  join cat_tree as parent on parent.id = child.parent_id
)
select *
from cat_tree;

已编辑

  @raw_sql """
  select id,parent_id
  from categories
  where id in (?)
  union all
    select child.id,child.parent_id
  from categories as child
    join cat_tree as parent on parent.id = child.parent_id
  """

  def category_search_query(query,[]),do: query 
  def category_search_query(query,category_ids) do
    query
    |> recursive_ctes(true)
    |> with_cte("cat_tree",as: fragment(@raw_sql,^category_ids))
    |> join(:inner,[b],c in "cat_tree",on: c.id == b.category_id)
  end

但是当我将 [12,13](例如)传递给函数时,它给了我以下错误

(DBConnection.EncodeError) Postgrex expected an integer in -9223372036854775808..9223372036854775807,got '\f\r'. Please make sure the value you are passing matches the deFinition in your table or in your query or convert the value accordingly.

但是当我只传递一个整数(而不是列表)时,它可以正常工作。

解决方法

我会制作一个程序来获取类别列表作为参数(可以是一个数组)并将您的查询更改为:

create function funcName (categoryIds int[])
returns table ( bookid int,categoryid int,...<deffine book columns>)
as 
$$ 
with recursive cat_tree as (
    select
        id,name,parent_id
    from
        categories
    where id in (select unnest(categoryIds))
    union all
    select
        child.id,child.name,child.parent_id
    from
        categories as child
    join cat_tree as parent on parent.id = child.parent_id
)
select
    b.*
from
    cat_tree c
join books on c.id = b.categoryid
$$ Language sql;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。