通过计算不同的列值来限制查询

时间:2017-08-18 07:19:30

标签: postgresql hibernate limit

我有一张人的桌子,像这样:

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

之前我将所有人员作为单独的对象返回API。因此,如果用户将限制设置为3,我只是将hibernate中的查询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,在下一页上返回另一半。

3 个答案:

答案 0 :(得分:1)

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

如果您没有Person表并且无法修改数据库,那么您可以使用SQL和Group By PersonId,并连接颜色

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

SQL Fiddle

答案 1 :(得分: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 :(得分:0)

谢谢你们。在我意识到用一个查询无法完成之后我就像

一样
len(array) // 4
len(array[0]) // 5

具有用户特定页面/ per_page

然后:

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