确定列表是否是另一个列表HQL的子集

时间:2012-12-04 17:05:44

标签: grails hql

我正在尝试为我的Grails应用程序编写一个查询,该应用程序选择AppleOrange实例“相关”的所有实例。这里“相关”一词意味着与Banana实例关联的Apple的所有实例都与Cherry的实例的某些组合相关联,这些实例与{{1}的实例相关联1}}我们关注。我查看了问题here,但我的查询有点复杂,而且我没有看到如何将给定答案应用于我的问题。

以下是我正在处理的课程:

Orange

图片形式如下:

enter image description here

在下面显示的方案1中,所需的查询只返回“Apple 1”,因为与“Apple 2”相关的所有class Apple { static hasMany = [ bananas: Banana ] } class Banana { } class Cherry { static hasMany = [ bananas: Bannna ] } class Orange { static hasMany = [ cherries: Cherry ] } 实例都与“Orange 1”无关,通过某种组合“樱桃”的实例。

enter image description here

在下面显示的方案2中,所需的查询将返回“Apple 1”和“Apple 2”,因为与“Apple 2”相关的Banana的所有实例都与“Orange 1”相关“樱桃”实例的某种组合。

enter image description here

以下是我一直在使用的查询:

Banana

问题是我的查询为方案1和2返回“Apple 1”和“Apple 2”。

更新#1:

根据要求,这是HQL查询生成的SQL。抱歉果味混淆<<<双关语

Apple.executeQuery(
    "SELECT DISTINCT apples
    FROM Apple apples
    INNER JOIN apples.banannas banannas
    WHERE banannas IN(
        SELECT DISTINCT banannas
        FROM Cherry cherries
        INNER JOIN cherries.banannas banannas
        WHERE cherries IN(
            SELECT DISTINCT cherries
            FROM Orange orange
            INNER JOIN orange.cherries cherries
            WHERE orange =:myOrange
        )
    )
    ORDER BY apples.id ASC",
    myOrange: myOrange
)

更新#2:

我实际上有一种方法可以使用HQL工作,但它不像我在其他地方找到所有类型与其他类型的实例相关的一个很好的衬里。这是我的工作:

SELECT DISTINCT apple0_.id                     AS id10_,
                apple0_.version                AS version10_,
                apple0_.description            AS descript3_10_,
                apple0_.apple_priority_type_id AS apple4_10_,
                apple0_.apple_status_type_id   AS apple5_10_,
                apple0_.internal_need_date     AS internal6_10_,
                apple0_.name                   AS name10_
FROM   apple apple0_
       INNER JOIN apple_priority_type applepri1_
               ON apple0_.apple_priority_type_id = applepri1_.id
       INNER JOIN apple_status_type applesta2_
               ON apple0_.apple_status_type_id = applesta2_.id
       INNER JOIN apple_banana banana3_
               ON apple0_.id = banana3_.apple_bananas_id
       INNER JOIN banana banana4_
               ON banana3_.banana_id = banana4_.id
WHERE  banana4_.id IN (SELECT DISTINCT banana7_.id
                       FROM   cherry plum5_
                              INNER JOIN cherry_banana banana6_
                                      ON plum5_.id = banana6_.cherry_bananas_id
                              INNER JOIN banana banana7_
                                      ON banana6_.banana_id = banana7_.id
                       WHERE  plum5_.id IN (SELECT DISTINCT plum10_.id
                                            FROM   orange orange8_
                                                   INNER JOIN orange_cherry
                                                              plum9_
                                                           ON
orange8_.id = plum9_.orange_cherrys_id
INNER JOIN cherry plum10_
        ON
plum9_.cherry_id = plum10_.id
WHERE  orange8_.id = 248))
ORDER  BY apple0_.id ASC
LIMIT  100 

1 个答案:

答案 0 :(得分:1)

那是因为如果你的Apple与香蕉至少有一个关系,那么总是会回来。

select
    distinct apple0_.id as id0_,
    apple0_.version as version0_ 
from
    apple apple0_ 
inner join
    apple_banana bananas1_ 
where bananas1_.banana_id in (1,2,3)

您需要做的是从结果中排除那些不存在与您的Cherry相关的香蕉的苹果。您必须查看您的数据库是否具有类似oracle minus 的功能。

编辑:此查询会从列表中删除那些香蕉不在樱桃香蕉中的苹果。

注意:我没有检查过它的性能。

  SELECT DISTINCT apples
    FROM Apple apples
    INNER JOIN apples.bananas bananas
    WHERE bananas IN(
        SELECT DISTINCT bananas
        FROM Cherry cherries
        INNER JOIN cherries.bananas bananas
        WHERE cherries IN(
            SELECT DISTINCT cherries
            FROM Orange orange
            INNER JOIN orange.cherries cherries
            WHERE orange =:myOrange
        )
    )
  and apples not in (
    SELECT DISTINCT apples
      FROM Apple apples
     INNER JOIN apples.bananas bananas
      WHERE bananas NOT IN(
        SELECT DISTINCT bananas
          FROM Cherry cherries
          INNER JOIN cherries.bananas bananas
          WHERE cherries IN(
            SELECT DISTINCT cherries
            FROM Orange orange
            INNER JOIN orange.cherries cherries
            WHERE orange = :myOrange
          )
      )
    )