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

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

3 голосов
/ 19 марта 2012

Краткая версия: Как мне написать этот запрос в 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?

1 Ответ

2 голосов
/ 19 марта 2012

Я бы не знал о 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
...