我有两个模式是这样的。
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毫秒。
试着用左连接和插入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)