Tengo una Hibernación de la entidad de que se parece a esto (descriptores de acceso omitido por razones de brevedad):

@Entity
@Table(name="FeatureList_Version")
@SecondaryTable(name="FeatureList",
    pkJoinColumns=@PrimaryKeyJoinColumn(name="FeatureList_Key"))
public class FeatureList implements Serializable {

    @Id
    @Column(name="FeatureList_Version_Key")
    private String key;

    @Column(name="Name",table="FeatureList")
    private String name;

    @Column(name="VERSION")
    private Integer version;

}

Quiero crear una consulta HQL que recupera la versión más actualizada de un FeatureList. La siguiente consulta tipo de obras:

Select f.name, max(f.version) from FeatureList f group by f.name

El problema es que no rellenar el campo de clave, que necesito para contener la clave del registro con el número de versión más alto para el FeatureList. Si puedo añadir f.clave en el select no funciona porque no está en el grupo, o un agregado y si lo pongo en el grupo por toda la cosa deja de funcionar y solo me da cada versión como una entidad separada.

Así, ¿alguien puede ayudar?

InformationsquelleAutor rjsang | 2010-12-21

5 Comentarios

  1. 58

    La sencilla versión de esta consulta se parece a esto (suponiendo que (name, version) pares son únicos):

    select f from FeatureList f 
    where f.version = 
         (select max(ff.version) from FeatureList ff where ff.name = f.name)
    • De hecho, su simple y más eficiente. En realidad, mirando group by en la consulta original me hizo reflexionar en torno a que todo ese tiempo. Yo consideraría esto un paso más en la reestructuración de mi propuesta de consulta. +1
  2. 13

    Hice un escenario de aquí,


    Tabla

    key          name                 version         
    ----------- -------------------- ----------- 
    1           adeel                1           
    2           adeel                2           
    3           adeel                3           
    4           ahmad                1           
    5           ahmad                2           
    6           ahmad                3           
    7           ahmad                4           
    8           ansari               1           
    9           ansari               2           
    10          ansari               3           

    El resultado de la consulta original

    >> select f.name, max(f.version) from FeatureList f group by f.name
    
    name                 max(f.version) 
    -------------------- ------------ 
    adeel                3            
    ahmad                4            
    ansari               3            

    El resultado de su consulta deseada

    >> select fl.* from FeatureList fl 
       where (fl.name, fl.version) in (select f.name, max(f.version) 
                                               from FeatureList f group by f.name);
    
    key          name                 max(fl.version)  
    ----------- -------------------- ----------- 
    3           adeel                3           
    7           ahmad                4           
    10          ansari               3           

    PD: Probé usando MySQL en este momento. Su trabajo. Estoy bastante seguro de MS SQL Server, también se han IN (...) operador. Usted sólo tiene que utilizar session.createNativeQuery() en modo de Hibernación.


    Editado para trabajar en axtavt la respuesta

    Como nos enteramos de esto puede ser hecho tan simple como,

    select f from FeatureList f 
    where f.version = 
         (select max(ff.version) from FeatureList ff where ff.name = f.name)

    Ahora a tratar de la misma mediante Hibernate Criterios API,

    DetachedCriteria versions = DetachedCriteria.forClass(FeatureList.class, "f")
        .setProjection( Property.forName("f.version").max())
        .add(Property.forName("f.name").eqProperty("fl.name"));
    
    session.createCriteria(FeatureList.class, "fl")
        .add( Property.forName("fl.version").eq(versions) )
        .list();
    • Muy bonito. +1 para que los criterios de aplicación
  3. 8

    Vieja pregunta, pero he pensado que me gustaría ofrecer mi experiencia aquí como para los futuros usuarios:

    select f from FeatureList f where f.version = 
     (select max(ff.version) from FeatureList ff where ff.name = f.name);

    Esto funciona muy bien, pero si el siguiente se tiene:

    • MySql v5.5 w/motor InnoDB
    • Usted sabe exactamente cuántas filas de resultados que usted desea (OC implica que s/él quiere exactamente 1 fila, pero la consulta anterior trabajo para un número variable de resultados)

    el siguiente parece ser muy significativamente más rápido:

    FROM FeatureList ORDER BY version DESC LIMIT 1;

    Mis pruebas en una consulta similar con 700.000 registros en la tabla tarda alrededor 0.19 s para la versión anterior y 0.05 s para el segundo.

  4. 3

    Cómo sobre esto,

    from FeatureList fl where (fl.name, fl.version) in (
                   select f.name, max(f.version) from FeatureList f group by f.name)

    Nota: Intente con el createNativeQuery(), su válida Oracle consulta, no estoy seguro acerca de cualquier otra base de datos.


    Una pregunta, es el par, name y version, único? Si sí, entonces su multa, de lo contrario, si la pareja no es el único, ¿qué piensa usted de cómo una clave serán seleccionados? Supongamos que uno de los antecedentes de la consulta original es,

    f.name         max(f.version)
    ------         --------------
    Django         1.2

    y asume que existen 3 keys tener el mismo par. Ahora la respuesta, lo que la clave debe ser asignado a este registro? Espero que usted está recibiendo mi punto.

    • No, eso no funciona porque no se puede poner de comparar dos valores para la subconsulta devuelve. Hibernate devuelve un SQLGrammarException quejarse de el , después de fl.nombre
    • Actualizado mi respuesta para continuar el debate.
    • Lamentablemente, esto no es una consulta válida en MSSQL, que necesita para ejecutarse. Nombre y versión del conjunto es único, pero si se añade clave en la agrupación que obtiene cada combinación de clave, nombre y versión de lo que significa cada versión diferente, en lugar de sólo el último (con el número de versión más alto)
    • No, se obtiene de la combinación de key y name, version no es la parte de group by aquí. Si el par es único, entonces mi propuesta 2ª consulta devolverá el mismo y el mismo número de registros. Intentar que fuera y que me haga saber.
    • Oh a la derecha. No, la clave y el nombre de la pareja no es única. La clave es la clave para la vinculación único de nombre y versión, por lo que un solo nombre tiene muchas teclas ya que tiene versiones.
    • Sí, por la única que me refiero name y version. Si hay un único key para el par, name y version, entonces mi consulta va a dar el mismo resultado. Intentar que fuera. Y quiero saber si hay alguna diferencia.

  5. 0

    Cómo sobre el uso de distintas + orden por lugar de grupo?

    select f.id, distinct(f.name), f.version from FeatureList f order by f.version desc

Dejar respuesta

Please enter your comment!
Please enter your name here