sql - 使用复杂的双连接来获取子对象的数量

标签 sql postgresql join

请注意,我使用的是 postgresql

我有一个organizations 表、一个users 表、一个jobs 表和一个documents 表。我想获得按组织有权访问的文档总数数量排序的组织列表。

organizations
------------
id (pk)
company_name

users
------------
id (pk)
organization_id

jobs
------------
id (pk)
client_id    (id of an organization)
server_id    (id of an organization)
creator_id   (id of a user)

documents
------------
id (pk)
job_id

期望的结果

organizations.id  |  organizations.company_name  |  document_count
85                |  Big Corporation             |  84
905               |  Some other folks            |  65
403               |  ACME, Inc                   |  14

如您所见,组织可以通过 3 种不同的路径连接到文档:

  1. organizations.id => jobs.client_id => documents.job_id
  2. organizations.id => jobs.server_id => documents.job_id
  3. organizations.id => users.organization_id => jobs.creator_id => documents.job_id

但是我想要一个查询来获取每家公司有权访问的所有文档的数量...

我尝试了一些事情......像这样:

SELECT COUNT(documents.id) document_count, organizations.id, organizations.company_name
FROM organizations
INNER JOIN users ON organizations.id = users.organization_id
INNER JOIN jobs ON (
  jobs.client_id = organizations.id OR
  jobs.server_id = organizations.id OR
  jobs.creator_id = users.id
)
INNER JOIN documents ON documents.job_id = jobs.id
GROUP BY organizations.id, organizations.company_name
ORDER BY document_count DESC
LIMIT 10

查询需要一段时间才能运行,但这并不可怕,因为我正在为一次性报告这样做,但结果...不可能是正确的。

第一个列出的组织报告了 129,834 个文档的数量——但这是不可能的,因为 documents 表中只有 32,820 个记录。我觉得它一定是在计算大量的重复项(由于我的一个连接出错?)但我不确定我哪里出错了。

顺序看起来是正确的,因为系统的最大用户显然位于列表的顶部......但该值不知何故膨胀了。

最佳答案

问题是,如果 jobs.client_id = organizations.idjobs.server_id = organizations.id,则没有什么可以过滤您的 INNER JOIN 用户(除了它的 ON 子句),因此您将获得属于该组织的每个用户的单独记录。换句话说,对于每个组织,您要添加三个值:

  • 它的用户总数乘以属于它作为客户的作业的文档总数
  • 它的用户总数乘以属于它作为服务器的作业的文档总数
  • 如果其用户是创建者,则属于作业的文档总数

解决此问题的一种方法是删除 INNER JOIN users 行,并将其更改为:

  jobs.creator_id = users.id

为此:

  jobs.creator_id IN (SELECT id FROM users WHERE organization_id = organizations.id)

. . .但这可能会表现得很糟糕。在找到性能可接受的查询之前,您可能需要尝试一些事情。

关于sql - 使用复杂的双连接来获取子对象的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14844308/

相关文章:

php - mysql + php 检索带路径的叶子节点

sql - 如何检查列是否没有null约束?

postgresql - Postgres : Distinct but only for one column

PostgreSQL:聚合成数组并连接

sql - 试图找到 SQL Server 安全性 : logins, 角色等的好图片/图表

sql - 遍历表中的组

postgresql - 在 pg_restore 中,如何使用 postgres 连接字符串来指定主机/数据库/用户名/密码?

mysql - 将多个选择与更新相结合

mysql - WordPressMU - 获取博客列表,按博客名称字母顺序排序

sql - 在SQL(Oracle)中将datetime字段转换为仅一个日期字段