La pregunta es por qué necesitarías una "consulta anidada"? No necesitamos usar "consultas anidadas", esto es pensar en la mentalidad de SQL no en Algebra Relacional. Con álgebra relacional derivamos las relaciones y usamos la salida de una relación como entrada a otro por lo que el siguiente sería válido:
points = Table(:points, {:as => 'sorted'}) # rename in the options hash
final_points = points.order('timestamp DESC').group(:client_id, :timestamp).project(:client_id, :timestamp)
Es mejor si dejamos el cambio de nombre a Arel a menos que sea absolutamente necesario.
Aquí la proyección de la indicación de fecha y hora client_id es MUY importante ya que no podemos proyectar todos los dominios de la relación (es decir, ordenado. *). Debe proyectar específicamente todos los dominios que se usarán dentro de la operación de agrupación para la relación. La razón es que no hay ningún valor para * que sea claramente representativo de un client_id agrupado. Por ejemplo supongamos que tiene la siguiente tabla
client_id | score
----------------------
4 | 27
3 | 35
2 | 22
4 | 69
Aquí si el grupo no se podía realizar una proyección en el dominio puntuación porque el valor podría ser o bien 27 o 69, pero se podría proyectar una suma (puntuación)
Solo puede proyectar los atributos de dominio que tienen valores únicos para el grupo (que generalmente son funciones agregadas como suma, máximo, mínimo). Con su consulta no importaría si los puntos fueron ordenados por marca de tiempo porque al final se agruparían por client_id. el orden de la marca de tiempo es irrelevante ya que no hay una sola marca de tiempo que pueda representar una agrupación.
Háganme saber cómo puedo ayudarlo con Arel. Además, he estado trabajando en una serie de aprendizaje para que la gente use Arel en su núcleo. La primera de la serie está en http://Innovative-Studios.com/#pilot . Puedo decir que están empezando a saber cómo usar Table (puntos) en lugar del Punto de modelo ActiveRecord.
Gracias por la respuesta detallada. "la orden de la marca de tiempo es irrelevante ya que no hay una sola marca de tiempo que pueda representar una agrupación". Tienes razón; Veo lo que dices. Parece que MySQL soluciona esta incoherencia devolviendo solo la primera fila del grupo client_id, que es lo que estaba buscando. Ahora veo que este no es un comportamiento con el que debería contar. Mi objetivo es devolver el punto más reciente para todos los client_ids, es decir, un único punto con la marca de tiempo máxima por cada agrupación client_id. Es importante hacerlo en una consulta porque se sondeará con frecuencia. – Schrockwell
Necesitaríamos usar alguna función agregada. Si nos preguntamos "¿Qué estamos tratando de hacer?" La respuesta sería encontrar la fecha más reciente o "máxima" para que pasemos max (timestamp) en sql. Esto correspondería a Arel :: Attribute :: Expression :: Maximum que puede invocarse con azúcar sintáctico en un Arel :: Attribute sort sort [: timestamp] .maximum(). Hay una advertencia. Asegúrese de agregar la marca de tiempo para agrupar la operación #group ('client_id, timestamp') o todo el escenario de agrupación generará un error. Sé que la función de agregado MAX funciona en fechas en Postgres y estoy seguro en MySQL también. – Snuggs
En primer lugar, la ordenación y el orden no son parte del álgebra relacional. Arel lo define de todos modos. En segundo lugar, si las subconsultas son parte del álgebra relacional es irrelevante. Conceptualmente, el resultado de un SELECT no es visible hasta que se ejecuta la cláusula WHERE. Por lo tanto, no todas las bases de datos (por ejemplo, Postgres) permiten alias de columna en las cláusulas WHERE y en su lugar dependen de subconsultas. Si Arel no puede manejar subconsultas, los nombres en la cláusula WHERE no pueden ser alias. Esto puede ser complicado cuando no puede depender de Arel para generar nombres. –