2012-03-19 2 views
3

Краткая версия: Как написать этот запрос в 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']. Внутренне он использует этот squeel код:

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?

+0

Что вы используете PostgreSQL? –

ответ

2

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

Some RDBMSs are happy with this, but postgres complains:

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

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

Allow non-GROUP BY columns in the query target list when the primary key is specified in the GROUP BY clause


BTW, ваш альтернативный запрос может быть упрощен, дополнительный 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 
+0

Это действительно приятно знать, спасибо! К сожалению, я запускаю приложение на heroku, поэтому обновление с 8.3 до 9.1 обойдется мне как минимум в 200 долларов в месяц, но если проблема связана с старыми версиями postgres, то, я думаю, я соглашусь с тем, что мне нужно работать с find_by_sql. Мне все еще любопытно, хотя, если squeel можно использовать для такого рода запросов. – dslh

+0

@dslh: [Лаборатории Heroku уже предлагают 9.1] (http://devcenter.heroku.com/articles/labs-heroku-shared-postgresql). Вам может быть интересно. –

+0

Это не отвечает на мой вопрос, но это решило мою проблему. Наверное, я задавал неправильный вопрос. Огромное спасибо! – dslh

Смежные вопросы