sql - 跨多个表查询避免联合所有

标签 sql postgresql

我尝试查询以下数据库表:

t_shared_users
user_id
user_category
folder_id
expiry

t_documents
id
folder_id
user_id
user_category
description
created
updated

t_folder
id
type
user_id
user_category
created
updated

我想找到您拥有并共享访问权限的所有文档。 IE。在 t_documents 中搜索所有文档,其中 user_id = 1 AND user_category = 100,但还将这些文档包含在您在 t_shared_users 中有权访问的文件夹中。这是我对查询的尝试:

  SELECT
    id,
    folder_id,
    user_id,
    user_category,
    description,
    created,
    updated
  FROM
    t_documents
  WHERE
    user_category = 100
    AND user_id = 1

  UNION ALL

  SELECT
    d.id,
    d.folder_id,
    d.user_id,
    d.user_category,
    d.description,
    d.created,
    d.updated
  FROM
    t_documents d
  JOIN
    t_shared_users s
  ON
    d.folder_id = s.folder_id
  WHERE
    d.user_category = 100
    d.AND user_id = 1

 ORDER BY
   created ASC
 LIMIT
   10

是否有更好/更高效/更简洁的方式来编写此查询?以上似乎有点冗长和缓慢。

编辑:

CREATE TABLE t_folder (
  id            SERIAL                   NOT NULL,
  user_category SMALLINT                 NOT NULL,
  user_id       INTEGER                  NOT NULL,
  type          INTEGER                  NOT NULL,
  description   TEXT,
  created       TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
  updated       TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
  PRIMARY KEY (id)
);

CREATE TABLE t_documents (
  id            BIGSERIAL                NOT NULL,
  folder_id     INTEGER,
  user_category SMALLINT                 NOT NULL,
  user_id       INTEGER                  NOT NULL,
  description   TEXT                     NOT NULL,
  created       TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
  updated       TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
  PRIMARY KEY (id)
);

CREATE TABLE t_shared_users (
  id            SERIAL,
  folder_id     INTEGER                  NOT NULL,
  user_category INTEGER                  NOT NULL,
  user_id       INTEGER                  NOT NULL,
  expiry        TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
  PRIMARY KEY (id)
);

最佳答案

这是您的查询:

  SELECT
    id,
    folder_id,
    user_id,
    user_category,
    description,
    created,
    updated
  FROM
    t_documents
  WHERE
    user_category = 100
    AND user_id = 1

  UNION ALL

  SELECT
    d.id,
    d.folder_id,
    d.user_id,
    d.user_category,
    d.description,
    d.created,
    d.updated
  FROM
    t_documents d
  JOIN
    t_shared_users s
  ON
    d.folder_id = s.folder_id
  WHERE
    d.user_category = 100
    AND d.user_id = 1 -- your query actually has a typo here

关于上述查询,我​​不明白的是为什么您要过滤 d.user_categoryd.user_id(t_documents 表) 在查询的底部。您确定您指的不是 s.user_categorys.user_id (t_shared_users) 吗?如果不是,加入 t_shared_users 有什么意义?

假设我认为您的查询有误是正确的,那么我将如何重写它:

select d.*
  from t_documents d
 where d.user_category = 100
   and d.user_id = 1
 union
select d.*
  from t_shared_users s
  join t_documents d
    on d.folder_id = s.folder_id
 where s.user_category = 100
   and s.user_id = 1

请注意,我使用的是 union 而不是 union all,因为我相信在技术上可能会以其他方式获得可能不需要的重复文档。

此外,作为一个粗略的近似值,这些是我为获得良好性能而定义的索引:

  • t_documents (user_id, user_category)
  • t_documents (folder_id)
  • t_shared_users(user_id、user_category、folder_id)

关于sql - 跨多个表查询避免联合所有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40055420/

相关文章:

mysql - 适用于 MySQL Workbench iODBC 的 Linux MS SQL ODBC 驱动程序

sql - 在 Postgresql 中动态获取别名

postgresql - 哪种类型的数据库索引有助于查询涉及比较两个字段?

python - 是否可以将 session.insert 用于 SQLAlchemy 中的一对主要关系?

mysql - 替换特定表中每一列中的字符串

sql - 如何在 SQL Server 中围绕动态数量的组对值进行分组

sql - 如何在重新定义依赖对象后刷新 T-SQL 用户定义函数的定义?

ruby-on-rails - 无法使用 where 子句 rails 检索信息

java - 有没有办法将 OrmLite 与 Postgres hstores 一起使用?

sql - 多选插入