1

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

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

class Apple {
    static hasMany = [ bananas: Banana ]
}

class Banana {
}

class Cherry {
    static hasMany = [ bananas: Bannna ]
}

class Orange {
    static hasMany = [ cherries: Cherry ]
}

以如下所示的图片形式:

在此处输入图像描述

在下面显示的场景 1 中,所需的查询将仅返回“Apple 1”,因为Banana与“Apple 2”相关的所有实例都通过“Cherry”实例的某种组合与“Orange 1”无关。

在此处输入图像描述

在下面显示的场景 2 中,所需查询将返回“Apple 1”和“Apple 2”,因为Banana与“Apple 2”相关的所有实例都通过“Cherry”实例的某种组合与“Orange 1”相关.

在此处输入图像描述

这是我一直在使用的查询:

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
)

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

更新#1:

根据要求,这里是 HQL 查询生成的 SQL。对不起,水果混淆了<<<双关语

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 

更新#2:

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

    def bananas= myOrange.cherries.bananas.flatten().unique()
    def apples = Apple.getAll().collectMany{ !it.bananas.isEmpty() && bananas.containsAll( it.bananas ) ? [ it ] : [] }.flatten().unique()
    namedParams.put( "apples", apples )
    if( !apples.isEmpty() ) {
        apples = Apple.executeQuery( "SELECT DISTINCT apples FROM Apple apples WHERE apples IN(:apples) ${additionalQuery} ORDER BY ${sortname} ${sortorder}", namedParams )
    }
    return apples
4

1 回答 1

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)

您需要做的是从您的结果中排除不存在与您的樱桃相关的香蕉的苹果。您将不得不查看您的数据库是否具有类似 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
          )
      )
    )
于 2012-12-04T21:05:04.483 回答