Вложенный запрос в squeel

Краткая версия: как мне написать этот запрос в squeel?

SELECT OneTable.*, my_count
FROM   OneTable JOIN (
  SELECT DISTINCT one_id, count(*) AS my_count
  FROM   AnotherTable
  GROUP BY one_id
) counts
ON OneTable.id=counts.one_id

Длинная версия: rocket_tag — это драгоценный камень, добавляющий простые теги к моделям. Он добавляет метод tagged_with. Предположим, моя модель User с идентификатором и именем, я мог бы вызвать User.tagged_with ['admin','sales']. Внутри он использует этот код шкворча:

select{count(~id).as(tags_count)}
.select("#{self.table_name}.*").
joins{tags}.
where{tags.name.in(my{tags_list})}.
group{~id}

Что генерирует этот запрос:

SELECT count(users.id) AS tags_count, users.*
  FROM users INNER JOIN taggings
    ON taggings.taggable_id = users.id
   AND taggings.taggable_type = 'User'
  INNER JOIN tags
    ON tags.id = taggings.tag_id
  WHERE tags.name IN ('admin','sales')
  GROUP BY users.id

Некоторым СУБД это нравится, но postgres жалуется:

ERROR: column "users.name" must appear in the GROUP BY
clause or be used in an aggregate function

Я считаю, что более приемлемым способом написания запроса было бы:

SELECT users.*, tags_count FROM users INNER JOIN (
  SELECT DISTINCT taggable_id, count(*) AS tags_count
    FROM taggings INNER JOIN tags
      ON tags.id = taggings.tag_id
    WHERE tags.name IN ('admin','sales')
    GROUP BY taggable_id
  ) tag_counts
  ON users.id = tag_counts.taggable_id

Есть ли способ выразить это с помощью squeel?


person dslh    schedule 19.03.2012    source источник
comment
Какая у вас версия PostgreSQL?   -  person Erwin Brandstetter    schedule 19.03.2012


Ответы (1)


Я бы не знал о Squeel, но ошибку, которую вы видите, можно исправить, обновив PostgreSQL.

Некоторым СУБД это нравится, но postgres жалуется:

ОШИБКА: столбец «users.name» должен присутствовать в предложении GROUP BY или использоваться в агрегатной функции.

Начиная с PostgreSQL 9.1, когда вы указываете первичный ключ в GROUP BY, вы можете пропустить дополнительные столбцы для этой таблицы и по-прежнему использовать их в списке SELECT. В примечаниях к выпуску версии 9.1 говорится:

Разрешить столбцы, отличные от GROUP BY, в списке целей запроса, если первичный ключ указан в предложении GROUP BY


Кстати, ваш альтернативный запрос можно упростить, дополнительный DISTINCT будет излишним.

SELECT o.*, c.my_count
FROM   onetable o
JOIN (
  SELECT one_id, count(*) AS my_count
  FROM   anothertable
  GROUP  BY one_id
) c ON o.id = counts.one_id
person Erwin Brandstetter    schedule 19.03.2012
comment
Это действительно приятно знать, спасибо! К сожалению, я запускаю приложение на героку, поэтому обновление с 8.3 до 9.1 обойдется мне как минимум в 200 долларов в месяц, но если проблема связана со старыми версиями postgres, то, думаю, я соглашусь с тем, что мне придется работать с найти_по_sql. Мне все еще любопытно, можно ли использовать squeel для такого рода запросов. - person dslh; 19.03.2012
comment
@dslh: Heroku Labs уже предлагает версию 9.1. Вы можете быть заинтересованы. - person Erwin Brandstetter; 19.03.2012
comment
Это не отвечает на мой вопрос, но решило мою проблему. Думаю, я задал неправильный вопрос. Большое спасибо! - person dslh; 23.03.2012