ActiveRecord, используя pluck с включенными / оставленными внешними объединениями
Когда я включаю его, левые присоединяются к таблице, по которой я хочу фильтровать, но когда я добавляю pluck, это объединение исчезает. Есть ли способ смешать pluck и левое соединение без ручного ввода SQL для "левого соединения"
Вот мой случай:
Select u.id
From users u
Left join profiles p on u.id=p.id
Left join admin_profiles a on u.id=a.uid
Where 2 in (p.prop, a.prop, u.prop)
Для этого просто загружаются все значения:
Users.includes(:AdminProfiles, :Profiles).where(...).map{ |a| a[:id] }
Но когда я делаю щипки вместо карты, она не покидает таблицы профилей.
1 ответ
Ваша проблема в том, что вы используете includes
который на самом деле не выполняет соединение, вместо этого он запускает второй запрос после первого, чтобы запросить ассоциации, в вашем случае вы хотите, чтобы они оба были фактически объединены, так что для замены includes(:something)
с joins(:something)
и все должно работать нормально.
Отвечая на ваш комментарий, я приведу несколько частей из руководства по рельсам об интерфейсе запроса активной записи.
Из раздела
Solution to N + 1 queries problem
clients = Client.includes(:address).limit(10) clients.each do |client| puts client.address.postcode end
Приведенный выше код будет выполнять только 2 запроса, в отличие от 11 запросов в предыдущем случае:
SELECT * FROM clients LIMIT 10 SELECT addresses.* FROM addresses WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
как видите, два запроса, вообще никаких соединений.
Из раздела
Specifying Conditions on Eager Loaded Associations
ссылка на сайтНесмотря на то, что Active Record позволяет вам задавать условия для загруженных ассоциаций точно так же, как и для объединений, рекомендуется вместо этого использовать объединения.
Тогда пример:
Article.includes(:comments).where(comments: { visible: true })
Это сгенерирует запрос, который содержит LEFT OUTER JOIN, тогда как метод joins сгенерирует запрос с использованием функции INNER JOIN.
SELECT "articles"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "articles" LEFT OUTER JOIN "comments" ON "comments"."article_id" = "articles"."id" WHERE (comments.visible = 1)
Если бы не было условия where, это сгенерировало бы нормальный набор из двух запросов.