【问题标题】:Limit query by count distinct column values通过计数不同的列值限制查询
【发布时间】:2017-08-18 07:19:29
【问题描述】:

我有一张人桌,像这样:

ID PersonId SomeAttribute
1  1        yellow
2  1        red
3  2        yellow
4  3        green
5  3        black
6  3        purple
7  4        white

以前我将所有 Persons 作为单独的对象返回给 API。因此,如果用户将限制设置为 3,我只是将休眠中的查询 maxResults 设置为 3 并返回:

{"PersonID": 1, "attr":"yellow"}
{"PersonID": 1, "attr":"red"}
{"PersonID": 2, "attr":"yellow"}

如果有人指定限制为 3 和第 2 页(setMaxResult(3), setFirstResult(6) 它将是:

{"PersonID": 3, "attr":"green"}
{"PersonID": 3, "attr":"black"}
{"PersonID": 3, "attr":"purple"}

但现在我想选择人,然后组合成一个 json 对象,如下所示:

{
 "PersonID":3, 
 "attrs": [
    {"attr":"green"},
    {"attr":"black"},
    {"attr":"purple"}
 ]
}

这就是问题所在。在 postgresql 或 hibernate 中是否有可能设置限制不是行数而是不同人员 ID 的数量,因为如果用户将限制指定为 4,我应该返回 person1、2、3 和 4,但在我当前的限制机制中,我会返回 person1 有 2 个属性, person2 和 person3 只有一个属性。分页也有同样的问题,现在我可以在一个页面上返回一半的 person3 数组 attrs,在下一页返回另一半。

【问题讨论】:

    标签: postgresql hibernate limit


    【解决方案1】:

    可以使用row_number模拟LIMIT

    -- Test data
    CREATE TABLE person AS 
        WITH tmp ("ID", "PersonId", "SomeAttribute") AS (   
            VALUES 
                (1, 1, 'yellow'::TEXT), 
                (2, 1, 'red'),
                (3, 2, 'yellow'),
                (4, 3, 'green'),
                (5, 3, 'black'),
                (6, 3, 'purple'),
                (7, 4, 'white')
            )
        SELECT * FROM tmp;
    
    -- Returning as a normal column (limit by someAttribute size)
    SELECT * FROM (
        select 
            "PersonId",
            "SomeAttribute",
            row_number() OVER(PARTITION BY "PersonId" ORDER BY "PersonId") AS rownum
        from 
            person) as tmp
    WHERE rownum <= 3;
    
    -- Returning as a normal column (overall limit)
    SELECT * FROM (
        select 
            "PersonId",
            "SomeAttribute",
            row_number() OVER(ORDER BY "PersonId") AS rownum
        from 
            person) as tmp
    WHERE rownum <= 4;
    
    -- Returning as a JSON column (limit by someAttribute size)
    SELECT "PersonId", json_object_agg('color', "SomeAttribute") AS attributes FROM (
        select 
            "PersonId",
            "SomeAttribute",
            row_number() OVER(PARTITION BY "PersonId" ORDER BY "PersonId") AS rownum
        from 
            person) as tmp
    WHERE rownum <= 3 GROUP BY "PersonId";
    
    -- Returning as a JSON column (limit by person)
    SELECT "PersonId", json_object_agg('color', "SomeAttribute") AS attributes FROM (
        select 
            "PersonId",
            "SomeAttribute"
        from 
            person) as tmp
    GROUP BY "PersonId"
    LIMIT 4;
    

    在这种情况下,当然,您必须使用native query,但恕我直言,这是一个小小的权衡。

    更多信息herehere

    【讨论】:

      【解决方案2】:

      谢谢你们。在我意识到它无法通过一个查询完成后,我只是做某事

      temp_query = select distinct x.person_id from (my_original_query) x
      

      带有用户特定页面/每页

      然后:

      my_original_query += " AND person_id in (temp_query_results)
      

      【讨论】:

        【解决方案3】:

        我假设您还有另一个 Person 表。使用 JPA,您应该在 Person 表(一侧)上进行查询,而不是在 PersonColor(多侧)上进行查询。然后将限制将应用于 Person 的行数然后

        如果你没有Person表并且不能修改DB,你可以使用SQL和Group ByPersonId,并连接颜色

        select PersonId, array_agg(Color) FROM my_table group by PersonId limit 2
        

        SQL Fiddle

        【讨论】:

        • 这个表 id、personID、属性只是为了可视化一个问题,它是一个带有返回 personId 和十几个其他属性的查询结果的表,所以连接它们不是一个好主意 imo : C
        • 然后在“一侧”上进行查询,在您的示例Person 表中。除此之外,我认为您无能为力。
        猜你喜欢
        • 2020-04-11
        • 1970-01-01
        • 1970-01-01
        • 2011-06-20
        • 2012-01-26
        • 2014-09-02
        • 2012-11-30
        • 2012-02-04
        • 2023-03-20
        相关资源
        最近更新 更多