如何在Hibernate中进行SELECT查询包括子查询COUNT(*)

时间:2012-03-24 16:02:18

标签: java sql database hibernate java-ee

假设我们有类别 - 商品 一对多关系。我想这样做

SELECT c.*, 
   (SELECT COUNT(*) FROM items i WHERE i.catId=c.id)
    AS itemCount
FROM category c

让我们说我们有一个Hibernate POJO“类别”。

我的第一个问题是我真的无法弄清楚从那个查询我得到一个List< Category>对象吧?我怎样才能访问“itemCount”?因为没有 Category.getItemCount()

其次,我如何编写Criteria查询?

由于

3 个答案:

答案 0 :(得分:6)

似乎这是我正在寻找的答案(进入POJO):

@Formula(value="(SELECT COUNT(*) FROM Items i WHERE i.id = id)")
@Basic(fetch=FetchType.EAGER)
public Integer getItemCount() {
   return this.taskCount;
}

答案 1 :(得分:2)

根据您的具体情况和创建视图的能力而定。我只想从你的查询中创建一个视图:

CREATE VIEW CategoryItemsView AS 
    SELECT c.*,  
   (SELECT COUNT(*) FROM items i WHERE i.catId=c.id) 
    AS itemCount 
FROM category c 

之后你可以查询你喜欢的...

SELECT * FROM CategoryItemsView WHERE ItemCount = 5

此外,您可以使用GROUP BY来获得类似的结果,但这取决于您的列和表的架构。

所以,像这样:

SELECT c.COLUMN1, c.COLUMN2, COUNT(*) AS ItemCount
FROM category c inner join items i on i.catID = c.Id
GROUP BY c.COLUMN1, c.COLUMN2
HAVING COUNT(*) = 2

答案 2 :(得分:1)

关于查询

受到@ a_horse评论的启发,我为了类似的目的,用真实的生命表进行了快速测试。

  • 80个类别
  • 6862件
  • 最佳索引(在items.catID上。还有更多,但在这里没用。)

三名候选人。结果是一样的。查询计划和性能各不相同。

1)每个类别的子选择(Seregwethrin的原始版本)

总运行时间:20.351 ms

SELECT c.*
      ,(SELECT COUNT(*) FROM items i WHERE i.catid = c.id) AS item_ct
FROM category c

2)LEFT JOIN,然后GROUP

总运行时间:36.320毫秒

SELECT c.*
      ,count(*) AS item_ct
FROM   category c
LEFT   JOIN items i ON i.catid = c.id
GROUP  BY c.catid;  -- prim. key of category

3)GROUP,然后LEFT JOIN

总运行时间: 18.588 ms

SELECT c.*
      ,item_ct
FROM   category c
LEFT   JOIN  (
    SELECT catid
          ,count(*) AS item_ct
    FROM   items
    GROUP  BY catid
    ) i ON i.catid = c.id

所以,我的第一个建议没有任何好处。正如预期的那样(经过一番思考),版本3)表现最佳。这也是有道理的:如果先计算,然后再加入,则需要更少的连接操作。

对于较大的表格,性能的差异将变得更加明显,特别是对于更多类别。

要使2)工作,你需要PostgreSQL 9.1和category.id作为主键 对于旧版本,您必须列出GROUP BY子句中的所有非聚合列。

我通常会切换到LEFT JOIN,因为原始查询包含没有相关项目的类别。

items.catID上的索引仅由1)使用,其中多个子查询可以获利。在其他查询中,顺序扫描更快:无论如何都必须读取所有表。