Ecto join上的 "不平等 "问题

问题描述 投票:0回答:1

我有两个模式是这样的。

schema "projects" do
  field :title, :string
  field :is_shared, :boolean
  timestamps()
end

schema "cards" do
  field :title, :string
  field :type, :string
  belongs_to(:project, Project)
end

现在我想找到项目中没有共享的卡。

我使用这个查询。

    from(c0 in Card,
      join:
        p1 in subquery(
          from p0 in Project,
            where: p0.is_shared == false,
            select: p0.id
        ),
      on: c0.project_id != p1.id,
      where: c0.type == "golden"
    )

但它给我一个Postgrex错误。

Postgrex.Protocol (#PID<0.494.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.527.0> timed out because it queued and checked out the connection for longer than 15000ms

但当我使用原始SQL语句调试打印时,就没有问题了。

SELECT c0."id",
       c0."title",
       c0."inserted_at",
       c0."updated_at"
FROM "cards" AS c0
         INNER JOIN (SELECT p0."id" AS "id" FROM "projects" AS p0 WHERE (p0."is_shared" = FALSE)) AS s1
                    ON c0."project_id" != s1."id"
WHERE (c0."type" = 'golden')

上面的原始sql是非常快的。它只花了100-200毫秒。

elixir ecto
1个回答
1
投票

试着用左连接和插入null Project id来做排除连接,像这样。

from(c0 in Card,
left_join: p1 in Project,
on: c0.project_id ==  p1.id,
where: is_nil(p1.id) and c0.type == "golden" and p1.is_shared == false,
select: c0)

还有,在ecto中处理==字符串时,你不需要^。

可能是你的查询试图在每一个不同的ID上连接一个ID,这意味着如果你做的是两张表,每张表有10,000行,你最终会有近100,000,000行。不知道为什么在你的原始sql中不会发生这种情况。

另外,如果你想 "找到项目中没有共享的卡片",你应该做一个基本的连接,而不是排除连接,像这样。

from(c0 in Card,
join: p1 in Project,
on: c0.project_id == p1.id,
where: c0.type == "golden" and p1.is_shared == false,
select: c0)
© www.soinside.com 2019 - 2024. All rights reserved.