【问题标题】:How to query subscription to an array field in postgresql/sql如何在 postgresql/sql 中查询对数组字段的订阅
【发布时间】:2018-06-07 20:09:39
【问题描述】:

我的数据包含可以分配多个类别(恐怖、戏剧、喜剧等)的书籍。用户可以订阅一个类别,我希望能够对具有指定类别的所有书籍的书籍表执行分页查询。示例架构:

CREATE TABLE IF NOT EXISTS books (
  bookid uuid PRIMARY KEY,
  categories uuid[],
  name text,
  author text,
  releasedate timestamp
);

CREATE TABLE IF NOT EXISTS categories (
  categoryid uuid PRIMARY KEY,
  name text
);

CREATE TABLE IF NOT EXISTS users (
  userid uuid PRIMARY KEY,
  name text
);

CREATE TABLE IF NOT EXISTS catsubscribers (
  categoryid uuid REFERENCES categories,
  userid uuid REFERENCES users,
  PRIMARY KEY (categoryid,  userid)
);

CREATE TABLE IF NOT EXIST bookcats (
  bookid uuid REFERENCES books,
  categoryid uuid REFERENCES categories,
  PRIMARY KEY (bookid, categoryid)
);

CREATE OR REPLACE FUNCTION getBooksBySubscribedCategory(me uuid, ofst integer, lim integer)
RETURNS TABLE(bookid uuid, categories uuid[], name text, author text, releasedate timestamp) AS $$
  DECLARE cid RECORD;
  BEGIN
    FOR cid IN (SELECT categoryid FROM catsubscribers WHERE userid = me)
    LOOP
      RETURN QUERY SELECT bks.bookid, bks.categories, bks.name, bks.author, bks.releasedate
      FROM (SELECT bookid, categories, name, author, releasedate FROM books WHERE bookid IN (SELECT bookid FROM bookcats WHERE categoryid = cid ) AS bks
      ORDER BY releasedate DESC
      OFFSET ofst
      LIMIT lim;
    END LOOP;
    RETURN;
  END;
$$ LANGUAGE plpgsql;

此函数获取用户订阅的类别数组,并遍历每个类别并查询 bookcats 联结表中的书籍。这是我的蛮力第一次尝试——它很丑,而且我不确定是否因为循环而使分页正确。有没有更好的方法来做到这一点?

【问题讨论】:

    标签: sql postgresql stored-procedures


    【解决方案1】:

    你根本不需要循环,

    RETURN QUERY 
    SELECT bks.bookid, bks.categories, bks.name, bks.author, bks.releasedate
    from books bks join bookcats bc on bc.bookid = bks.bookid
    join catsubscribers cs on cs.categoryid = bc.categoryid
    where cs.userid = me 
    group by bks.bookid, bks.categories, bks.name, bks.author, bks.releasedate
    limit lim offset ofst
    

    【讨论】:

    • 我认为可能有一个'intersection'类型的选项,但我认为多重连接会有更好的性能?
    • 是的,多个连接很好,只要确保您已将它们设置为外键,如果数据集很大,索引它们将进一步提高性能。
    【解决方案2】:

    OFFSETLIMIT 是经典选择,但是当您遇到性能问题时可能会出现其他注意事项:https://use-the-index-luke.com/blog/2013-07/pagination-done-the-postgresql-wayhttps://use-the-index-luke.com/sql/partial-results/fetch-next-page 很好地概述了如何实现高性能分页。

    结果是维护外部所需的页面状态,而不是偏移/限制,使用WHERE 过滤器通过在当前页面之前过滤(在这种情况下)releasedate 直接获取相关行并限制它的页面大小。

    【讨论】:

      猜你喜欢
      • 2015-04-13
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 2017-06-13
      • 2018-03-25
      • 2014-11-09
      • 2019-08-16
      • 2017-07-15
      相关资源
      最近更新 更多