postgresql 如何在postgres中跨多行查询

iswrvxsc  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(1)|浏览(156)

我使用Postgres中的以下两个表保存动态对象(我不知道其类型的对象):

CREATE TABLE IF NOT EXISTS objects(
    id UUID NOT NULL DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,

    name TEXT NOT NULL,

    PRIMARY KEY(id)
);

CREATE TABLE IF NOT EXISTS object_values(
    id UUID NOT NULL DEFAULT gen_random_uuid(),
    event_id UUID NOT NULL,

    param TEXT NOT NULL,
    value TEXT NOT NULL,
);

例如,如果我有以下对象:

dog = [
  { breed: "poodle", age: 15, ...},
  { breed: "husky", age: 9, ...},
}
monitors = [
  { manufacturer: "dell", ...},
}

它将按如下方式保存在DB中:

-- objects
| id | user_id | name    |
|----|---------|---------|
| 1  | 1       | dog     |
| 2  | 2       | dog     |
| 3  | 1       | monitor |

-- object_values
| id | event_id | param        | value  |
|----|----------|--------------|--------|
| 1  | 1        | breed        | poodle |
| 2  | 1        | age          | 15     |
| 3  | 2        | breed        | husky  |
| 4  | 2        | age          | 9      |
| 5  | 3        | manufacturer | dell   |

注意,这些表很大(数亿个)。通常为编写优化。基于多个对象参数查询/过滤对象的好方法是什么?例如:选择每个唯一用户年龄超过10的所有husky犬的数量。
我还想知道,如果对表进行非规范化处理,并将参数折叠到JSON列(并使用gin索引),是否会更好。
有什么标准我可以用吗?

lo8azlld

lo8azlld1#

"* 选择每个唯一用户拥有的10岁以上的所有哈士奇狗的数量 *"-下面的查询将完成此操作。

SELECT user_id, COUNT(DISTINCT event_id) AS num_husky_dogs_older_than_10
FROM       objects       o
INNER JOIN object_values ov
        ON o.id_ = ov.event_id
       AND o.name_ = 'dog'
GROUP BY o.user_id
HAVING MAX(CASE WHEN ov.param = 'age' 
                 AND ov.value_::integer >= 10 THEN 1 END) = 1
   AND MAX(CASE WHEN ov.param = 'breed'
                 AND ov.value_ = 'husky'      THEN 1 END) = 1;

由于您的查询最有可能受到这两个表之间对相同字段执行相同JOIN操作的影响,因此最好在以下位置使用indices

  • 您联接的字段("* 对象. ID "、" 对象值.事件ID *")
  • 过滤所依据的字段("* 对象.名称 "、" 对象值.参数 "、" 对象值.值 *")

检查here演示。

相关问题