Вопрос в том, зачем вам нужен «вложенный запрос»? Нам не нужно использовать «вложенные запросы», это мышление в мышлении SQL не реляционной алгебры. С реляционной алгебры мы выводим отношения и использовать выход одного отношения в качестве вклада в другую, так что следующий будет справедливы:
points = Table(:points, {:as => 'sorted'}) # rename in the options hash
final_points = points.order('timestamp DESC').group(:client_id, :timestamp).project(:client_id, :timestamp)
Это лучше, если мы оставим переименовывать не AREL, если это абсолютно необходимо.
Здесь проекция client_id AND timestamp очень важна, поскольку мы не можем проецировать все домены из отношения (то есть отсортированного. *). Вы должны специально спроектировать все домены, которые будут использоваться в операции группировки для отношения. Причина в том, что для * нет значения для *, которое будет отчетливо представлять собой сгруппированный client_id. Например, у вас есть следующая таблица
client_id | score
----------------------
4 | 27
3 | 35
2 | 22
4 | 69
Здесь, если вы группа не можете выполнить проекцию на домен бального, поскольку значение может быть либо 27 или 69, но вы можете проецировать сумму (оценку)
Вы можете проектировать только атрибуты домена, которые имеют уникальные значения для группы (которые обычно являются совокупными функциями, такими как sum, max, min). По вашему запросу было бы неважно, были ли точки отсортированы по метке времени, потому что в итоге они были бы сгруппированы по client_id. порядок временной отметки не имеет значения, поскольку нет единой метки времени, которая могла бы представлять группировку.
Пожалуйста, дайте мне знать, как я могу помочь вам с Арелем. Кроме того, я работаю над учебной серией, чтобы люди могли использовать Arel в своей основе. Первая из серии - http://Innovative-Studios.com/#pilot Я могу сказать, что вы начинаете знать, как с тех пор, как вы использовали таблицу (: points), а не точку модели ActiveRecord.
Благодарим вас за подробный ответ. «заказ временной метки не имеет значения, поскольку нет единой метки времени, которая могла бы представлять группировку». Ты прав; Я вижу, что вы говорите. Похоже, что MySQL работает над этой несогласованностью, возвращая только первую строку группы client_id, к чему я стремился. Теперь я вижу, что это не поведение, на которое я должен рассчитывать. Моя цель - вернуть самую последнюю точку для всех клиентов, т. Е. Одну точку с максимальной меткой времени для каждой группы client_id. Это важно сделать в одном запросе, потому что он будет часто опрошен. – Schrockwell
Нам нужно будет использовать некоторую функцию агрегата. Если мы спросим себя: «Что мы пытаемся сделать?» Ответ будет заключаться в том, чтобы найти самую последнюю или «максимальную» дату, чтобы мы могли передать max (timestamp) в sql. Это соответствовало бы Arel :: Attribute :: Expression :: Maximum, который можно вызвать с помощью синтаксического сахара в атрибуте Arel :: Attribute, например sorted [: timestamp] .maximum(). Есть одно предостережение. Убедитесь, что вы добавили временную метку для групповой операции #group ('client_id, timestamp') или весь сценарий группировки. Я знаю, что функция агрегации MAX работает с датами в Postgres, и я уверен и в MySQL. – Snuggs
Во-первых, сортировка и порядок не являются частью реляционной алгебры. Арель все равно определяет это. Во-вторых, независимо от того, являются ли подзапросы частью реляционной алгебры, не имеет значения. Понятно, что результат SELECT не отображается до тех пор, пока не будет выполнено предложение WHERE. Поэтому не все базы данных (например, Postgres) допускают псевдонимы столбцов в предложениях WHERE и зависят от подзапросов. Если Arel не может обрабатывать подзапросы, тогда имена в предложении WHERE не могут быть сглажены. Это может стать беспорядочным, если вы не можете зависеть от Arel для генерации имен. –