带条件的Ecto片段子查询where

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

我试图使用ecto执行一个查询,并将子查询作为其中一个 SELECTs. 在SQL中是这样的(player has_many votes):

SELECT
    players.id AS player_id,
    (SELECT count(*) FROM votes WHERE votes.player_id = players.id) AS vote_count
FROM
    players

然而,根据一个参数的存在,我想用 SELECT 子查询有一个额外的 WHERE 条款。例如

SELECT
    players.id AS player_id,
    (SELECT count(*) FROM votes WHERE votes.player_id = players.id AND votes.type = 'motm') AS vote_count
FROM
    players

在ecto中,我想出了这样的办法。

vote_count_query =
  from(p in Player,
    select: %{
      player_id: p.id,
      vote_count:
        fragment(
          "SELECT count(*) FROM votes WHERE votes.player_id = ?",
          p.id
        )
    }
  )

假设有一个变量 vote_type 有无 nil,我怎么能有条件地添加一个 where 子句到内部选择子查询?例如

fragment(
  "SELECT count(*) FROM votes WHERE votes.player_id = ? AND votes.type = ?",
  p.id,
  ^vote_type
)

(如果有更好的方法来获取票数,则可以通过 玩家,那么我会很高兴听到。在连接的情况下,似乎没有投票存在的玩家不会被返回)。)

sql elixir ecto
1个回答
0
投票

虽然 评语 由 @dogbert 所做的看起来可能会成功,我通过将 SELECT 子查询替换为左连接来实现。

def vote_count(team_id, vote_type \\ nil) do
  vote_count_query =
    Player
    |> select([p, v], %{
      player_id: p.id,
      vote_count: count(v.id)
    })
    |> where([p, _], p.team_id == ^team_id)
    |> group_by([p, _], p.id)

  # depending on whether we are filtering by vote_type use the appropriate join
  # condition
  if(is_nil(vote_type),
    do: vote_count_query |> join(:left, [p], v in assoc(p, :votes)),
    else:
      vote_count_query
      |> join(:left, [p], v in Vote, on: p.id == v.player_id and v.type == ^vote_type)
  )
end

看来关键是要使用 左边 在加入条件中加入票数类型的外部加入,而不是默认的内部加入。否则结果中不会返回0票的玩家。

© www.soinside.com 2019 - 2024. All rights reserved.