代码之家  ›  专栏  ›  技术社区  ›  Vinnie

jpql获取最近的行

  •  2
  • Vinnie  · 技术社区  · 16 年前

    假设我有下表

    my_profile_data
    -------------
    integer: my_profile_data_id
    integer: profile_id
    integer: profile_data_type_id
    date: date_changed
    string: value
    
    my_profile
    -------------
    integer: profile_id
    string: name
    
    profile_data_type
    -------------
    integer: profile_data_type_id
    string: name
    

    我想获取每个配置文件数据类型的最新配置文件信息。在纯SQL中,这看起来像:

    select mpd.profile_id, mpd.profile_data_type_id, mpd.value, max(mpd.date_changed) 
    from my_profile_data mpd, my_profile mp 
    where mpd.profile_id = mp.profile_id and mp.name='The Profile I Want' 
    group by mpd.profile_data_type_id
    

    我尝试过以下JPQL查询的不同变体,但无法使其正常工作。

    SELECT mpd FROM MyProfileData mpd LEFT JOIN
         (SELECT mpd.profileId profileId, MAX(mpd.dateChanged) FROM MyProfileData mpd
         LEFT JOIN mp.profile
         WHERE mp.name = :name
         GROUP BY mpd.profileDataTypeId) recent
    ON (rp.profileid = recent.profileId)
    

    这个查询在JPA中可行吗?

    我使用EclipseLink作为我的JPA提供者。

    当我尝试运行时,我得到的最内部的异常是

    Caused by: NoViableAltException(81!=[506:7: (n= joinAssociationPathExpression ( AS )? i= IDENT | t= FETCH n= joinAssociationPathExpression )])
        at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.join(JPQLParser.java:3669)
        ... 73 more
    
    2 回复  |  直到 15 年前
        1
  •  0
  •   Affe    16 年前

    假设日期实际上是一个您不担心冲突的时间戳,那么您的查询就好像

    select mpd 
    from MyProfileData mpd
    where mpd.profile.name = :name
    and mpd.date = (select max(mpd1.date) from MyProfileData mpd1 where mpd1.profile.name = :name)
    

    你在使用DBMS吗,就像旧的MySQL那样,讨厌子选择?

    我也在想,也许您的问题是您还没有将对象关系从myprofiledata映射到profiledata,您所拥有的只是字段的实际整数值。这通常会使编写JPQL查询非常困难。

    编辑:

    继续假设日期不会与任何给定的profile+profile数据类型组合冲突(因此,日期唯一地标识特定profile+profile类型组合子集中的行),您可以只获取所有日期:

        select mpd from MyProfileData
        where mpd.profile.name = :name
        and mpd.date in (select max(mpd1.date) 
                         from MyProfileData mpd1 
                         where mpd1.profile = mpd.profile group by mpd.profileDataType)
    

    您最初的SQL示例实际上是不合法的,因此很难想出一种方法来重现它试图做的事情,而不需要在排除值的同时唯一地标识行。

        2
  •  -1
  •   Vinnie    15 年前

    我放弃了在JPA中创建这个查询,而是编写了一个本机查询。