在 Postgres SELECT 语句中选择另一个表中的行数

发布于 2024-10-09 13:51:52 字数 400 浏览 1 评论 0原文

我不太知道如何表达这个,所以也请帮我写一下标题。 :)

我有两张桌子。我们将它们称为 ABB 表有一个指向 A.ida_id 外键。现在我想编写一个 SELECT 语句来获取所有 A 记录,并附加一个列,其中包含每个 B 记录的计数结果集中的每一行都有一个 行。

我现在正在使用 Postgresql 9,但我想这将是一个通用的 SQL 问题?

编辑:

最后我选择了触发器缓存解决方案,其中每次 B 更改时都会通过函数更新 A.b_count 。

I don't know quite how to phrase this so please help me with the title as well. :)

I have two tables. Let's call them A and B. The B table has a a_id foreign key that points at A.id. Now I would like to write a SELECT statement that fetches all A records, with an additional column containing the count of B records per A row for each row in the result set.

I'm using Postgresql 9 right now, but I guess this would be a generic SQL question?

EDIT:

In the end I went for trigger-cache solution, where A.b_count is updated via a function each time B changes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蓝海 2024-10-16 13:51:52
SELECT A.*, (SELECT COUNT(*) FROM B WHERE B.a_id = A.id) AS TOT FROM A
SELECT A.*, (SELECT COUNT(*) FROM B WHERE B.a_id = A.id) AS TOT FROM A
蝶…霜飞 2024-10-16 13:51:52

我认为 @intgr 在另一个答案中的评论非常有价值,我将其作为替代答案提出,因为此方法允许您有效地过滤计算列。

SELECT
  a.*,
  COUNT(b.id) AS b_count

FROM a
INNER JOIN b on b.a_id = a.id
WHERE a.id > 50 AND b.ID < 100 -- example of filtering joined tables, optional

GROUP BY a.id
HAVING COUNT(b.id) > 10 -- example of filtering calculated column, optional
ORDER BY a.id

I think the comment by @intgr in another answer is so valuable I'm putting forward this as an alternate answer as this method allows you to filter the calculated column efficiently.

SELECT
  a.*,
  COUNT(b.id) AS b_count

FROM a
INNER JOIN b on b.a_id = a.id
WHERE a.id > 50 AND b.ID < 100 -- example of filtering joined tables, optional

GROUP BY a.id
HAVING COUNT(b.id) > 10 -- example of filtering calculated column, optional
ORDER BY a.id
一江春梦 2024-10-16 13:51:52

上面给出的子查询解决方案效率很低。触发器解决方案可能在大多数读取的数据库中是最好的,但为了记录,这里有一种连接方法,其性能比子查询更好:

SELECT a.id, a.xxx, count(*)
FROM a JOIN b ON (b.a_id = a.id)
GROUP BY a.id, a.xxx

如果您使用 Django ORM,您可以简单地编写:

res = A.objects.annotate(Count('b'))
print res[0].b__count  # holds the result count

The subquery solution given above is inefficient. The trigger solution is probably best in a mostly-read database, but for the record here's a join approach that will perform better than a subquery:

SELECT a.id, a.xxx, count(*)
FROM a JOIN b ON (b.a_id = a.id)
GROUP BY a.id, a.xxx

If you're using Django ORM you can simply write:

res = A.objects.annotate(Count('b'))
print res[0].b__count  # holds the result count
那一片橙海, 2024-10-16 13:51:52

根据我的测试,接受的答案效率低下(慢)。表 B 的子查询对表 A 的每一行执行。我使用以下基于分组和联接的方法。它的工作速度更快:

SELECT A.id, QTY.quantity FROM A
LEFT JOIN
    (SELECT COUNT(B.a_id) AS quantity, B.a_id FROM B GROUP BY B.a_id) AS QTY
ON A.id = QTY.a_id

另一种变体:

SELECT A.id, COUNT(B.a_id) AS quantity FROM A
LEFT JOIN B ON B.a_id = A.id
GROUP BY A.id

Accepted answer is inefficient (slow) based on my tests. The subquery of table B executing for every row of table A. I'm using following approach based on grouping and joining. It works much faster:

SELECT A.id, QTY.quantity FROM A
LEFT JOIN
    (SELECT COUNT(B.a_id) AS quantity, B.a_id FROM B GROUP BY B.a_id) AS QTY
ON A.id = QTY.a_id

Another variant:

SELECT A.id, COUNT(B.a_id) AS quantity FROM A
LEFT JOIN B ON B.a_id = A.id
GROUP BY A.id
给我一枪 2024-10-16 13:51:52

回答我自己的问题:

SELECT a.id, a.other_column, ..., 
(SELECT COUNT(*) FROM b where b.a_id = a.id) AS b_count
FROM a;

To answer my own question:

SELECT a.id, a.other_column, ..., 
(SELECT COUNT(*) FROM b where b.a_id = a.id) AS b_count
FROM a;
尽揽少女心 2024-10-16 13:51:52

虽然子查询的效率可能较低,但效率降低的程度取决于用例。另一件需要考虑的事情是正在使用的过滤器。

我有一个“批准者”表 A
我有一个“审批任务”表 B,

我想显示所有审批者的列表以及他们拥有的活动审批任务的计数。现在,我对 SQL 的了解有限,但无论我尝试使用不同类型的联接,我的批准者列表都是不完整的。为什么?我需要在表 B 上有一个过滤器,以便只返回活动任务。如果审批者只有非活动/已完成的任务,则没有计数。这应该显示 0,但由于某种原因它根本不显示该行。

所以,我使用了子查询,它工作得很好。

Whilst a sub-query may be less efficient, how much less efficient depends on the use-case. Another thing to consider is the filters that are being used.

I have a Table A of "Approvers"
I have a Table B of "Approval tasks"

I want to show a list of ALL approvers along with a count of how many ACTIVE approval tasks they have. Now, my knowledge of SQL is limited, but no matter what I tried with the different types of join, my list of approvers was incomplete. Why? I need to have a filter on table B so that only active tasks are returned. If an approver only has inactive/complete tasks, there is no count. This should show 0, but for some reason it just doesn't show the row at all.

So, I use a sub-query and it works perfectly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文