First of all, you might want to use a %Q{...}
string and some formatting in your SQL to avoid an unreadable mess:
Pick.find_by_sql(%Q{
WITH
cte1 AS (
SELECT DISTINCT user_id, state, pick
FROM picks
WHERE id IN (#{pick_ids})
),
cte2 AS (
SELECT user_id, coalesce(sum(amount_won), 0) as picks_total_won
FROM picks
WHERE id IN (#{pick_ids})
GROUP BY user_id
),
cte3 AS (
SELECT user_id, COUNT(CASE WHEN state = 'won' then 1 ELSE null END) AS picks_won,
FROM cte1
GROUP BY user_id
)
SELECT cte2.picks_total_won, cte3.picks_won
FROM cte2
JOIN cte3 ON cte2.user_id = cte3.user_id
})
Depending on where your picks
come from, you might be able to avoid the interpolation completely and embed the SQL to generate the pick_ids
(possibly using another CTE).
If you need to feed the pick_ids
in from the outside world then you can use placeholders with find_by_sql
but the interface is a bit bizarre: you have to pass an array to find_by_sql
:
Pick.find_by_sql([%Q{
WITH
cte1 AS (
SELECT DISTINCT user_id, state, pick
FROM picks
WHERE id IN (:pick_ids)
),
cte2 AS (
SELECT user_id, coalesce(sum(amount_won), 0) as picks_total_won
FROM picks
WHERE id IN (:pick_ids)
GROUP BY user_id
),
cte3 AS (
SELECT user_id, COUNT(CASE WHEN state = 'won' then 1 ELSE null END) AS picks_won,
FROM cte1
GROUP BY user_id
)
SELECT cte2.picks_total_won, cte3.picks_won
FROM cte2
JOIN cte3 ON cte2.user_id = cte3.user_id
}, :pick_ids => some_array_of_ids])
Note the location of the [
and ]
in the argument list.