需要将 LEFT JOIN 转换为 JPQL

发布于 2024-12-04 22:21:09 字数 1298 浏览 3 评论 0原文

想象一下以下问题: 有人想买一篮子水果,里面有来自非洲和南美的绿色水果,但没有来自非洲的红色水果。

为此,我们考虑以下类:



    class Basket
    {
      int id;
      Collection<Fruit> fruits; 
    }

    class Fruit
    {
      int id;
      int basketId;
      String origin
      Color color;
    }

映射将为 MxM。 Fruit 的目的是没有 Basket 对象,但如果需要的话我可以实现它。

对于本机 SQL,我将使用:



    SELECT * 
    FROM 
      Basket b 
    JOIN 
    (
      SELECT DISTINCT basketId 
      FROM Fruit 
      WHERE color='green' AND (origin='Africa' OR origin='South America')
    ) f1 ON (b.id=f1.basketId) 
    LEFT JOIN 
    (
      SELECT DISTINCT basketId 
      FROM Fruit 
      WHERE color='red' AND (origin='Africa')
    ) f2 ON (b.id=f2.basketId) 
    WHERE f2.basketId IS NULL 

JPQL 中的查询是什么?

我已经尝试过以下操作:



    SELECT b 
    FROM Basket b 
    WHERE 
      b.id IN (
        SELECT f1.basketId FROM Fruit f1 
        WHERE f1.color='green' AND (f1.origin='Africa' OR f1.origin='South America')
      ) AND
      b.id NOT IN (
        SELECT f2.basketId FROM Fruit f2 
        WHERE f2.color='red' AND (origin='Africa'))

但是这个查询花费了 12000 毫秒而不是 50 毫秒。 (这只是一个简单的例子。真正的表有大约 750000 个“水果”和 10000 个“篮子”,每个篮子有更多的字段。)

提前致谢

Gerald

immagine following problem:
somebody wants to buy a basket of fruit containing green fruits from Africa and South America but no red fruits from Africa.

for that we think about following classes:



    class Basket
    {
      int id;
      Collection<Fruit> fruits; 
    }

    class Fruit
    {
      int id;
      int basketId;
      String origin
      Color color;
    }

the mapping will be MxM.
It is intended that Fruit has no Basket object, but if necessary i could implement it.

for Native SQL i would use:



    SELECT * 
    FROM 
      Basket b 
    JOIN 
    (
      SELECT DISTINCT basketId 
      FROM Fruit 
      WHERE color='green' AND (origin='Africa' OR origin='South America')
    ) f1 ON (b.id=f1.basketId) 
    LEFT JOIN 
    (
      SELECT DISTINCT basketId 
      FROM Fruit 
      WHERE color='red' AND (origin='Africa')
    ) f2 ON (b.id=f2.basketId) 
    WHERE f2.basketId IS NULL 

What will be the Query in JPQL?

i tried already following:



    SELECT b 
    FROM Basket b 
    WHERE 
      b.id IN (
        SELECT f1.basketId FROM Fruit f1 
        WHERE f1.color='green' AND (f1.origin='Africa' OR f1.origin='South America')
      ) AND
      b.id NOT IN (
        SELECT f2.basketId FROM Fruit f2 
        WHERE f2.color='red' AND (origin='Africa'))

but this query took 12000ms instead of 50 ms.
(This is just a simple example. The real Tables have around 750000 "fruits" and 10000 "baskets" with much more fields each.)

Thanks in advance

Gerald

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼泪也成诗 2024-12-11 22:21:10

你可以尝试

select b from Basket b where
    exists (select f.id from Fruit f where f.basket = b and f.color = 'green')
    and not exists (select f.id from Fruit f where f.basket = b and f.color = 'red')

,但我不确定它会更快。这取决于执行计划,而执行计划又取决于数据库索引。 Fruit.basketIdFruit.color 上应该有一个索引。

You could try

select b from Basket b where
    exists (select f.id from Fruit f where f.basket = b and f.color = 'green')
    and not exists (select f.id from Fruit f where f.basket = b and f.color = 'red')

But I'm not sure it would be faster. It depends on the execution plan, which depends on the database indexes. There should be an index on Fruit.basketId and on Fruit.color.

活泼老夫 2024-12-11 22:21:10

这行得通吗?

select b from Basket b join b.fruits f where f.color = 'green' and not f.color = 'red';

连接可能是可选的,因此也可以是

select b from Basket b where b.fruits.color = 'green' and not b.fruits.color = 'red';

would this work?

select b from Basket b join b.fruits f where f.color = 'green' and not f.color = 'red';

The join is probably optional so it could also be

select b from Basket b where b.fruits.color = 'green' and not b.fruits.color = 'red';
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文