我试图让下面的代码返回PostgreSQL中使用左连接的每个组织的计数,但我不知道为什么它不起作用:
select o.name as organisation_name,
coalesce(COUNT(exam_items.id)) as total_used
from organisations o
left join exam_items e on o.id = e.organisation_id
where e.item_template_id = #{sanitize(item_template_id)}
and e.used = true
group by o.name
order by o.name
字符串
使用coalesce
似乎不起作用。我已经黔驴技穷了!任何帮助都将不胜感激!
为了澄清什么不起作用,目前查询只返回计数大于0的组织的值。我希望它为每个组织返回一行,而不管计数如何。
表格定义:
TABLE exam_items
id serial NOT NULL
exam_id integer
item_version_id integer
used boolean DEFAULT false
question_identifier character varying(255)
organisation_id integer
created_at timestamp without time zone NOT NULL
updated_at timestamp without time zone NOT NULL
item_template_id integer
stem_id integer
CONSTRAINT exam_items_pkey PRIMARY KEY (id)
TABLE organisations
id serial NOT NULL
slug character varying(255)
name character varying(255)
code character varying(255)
address text
organisation_type integer
created_at timestamp without time zone NOT NULL
updated_at timestamp without time zone NOT NULL
super boolean DEFAULT false
CONSTRAINT organisations_pkey PRIMARY KEY (id)
型
2条答案
按热度按时间mccptt671#
修复
LEFT JOIN
这应该可以:
字符串
你有一个
LEFT [OUTER] JOIN
,但后来的WHERE
条件使它表现得像一个普通的[INNER] JOIN
。将条件移动到
JOIN
子句中,使其按预期工作。这样,首先只连接满足所有这些条件的行(或者 right 表中的列填充为NULL)。就像您所做的那样,连接的行实际上在LEFT JOIN
之后 * 测试附加条件,如果它们不通过,则将其删除,就像普通的JOIN
一样。count()
从开始就从不返回NULL。在这方面,它是聚合函数中的一个例外。因此,COALESCE(COUNT(col))
never 是有意义的,即使有额外的参数。The manual:需要注意的是,除了
count
,当没有选择行时,这些函数返回空值。粗体强调我的。参见:
count()
必须位于定义为NOT NULL
的列上(如e.id
),或者连接条件保证NOT NULL
(e.organisation_id
、e.item_template_id
或e.used
)。由于
used
的类型是boolean
,表达式e.used = true
是噪声,只剩下e.used
。由于
o.name
没有定义为UNIQUE NOT NULL
,所以您可能希望改为GROUP BY o.id
(id
是PK)-除非您打算折叠具有相同名称(包括NULL)的行。先聚合后加入
如果
exam_items
的大多数或所有行都在这个过程中被计算,那么这个等价的查询通常会更快/更便宜:型
(This假设您不想像上面提到的那样折叠同名的行-这是典型的情况。)
现在我们可以在子查询中使用更快/更简单的
count(*)
,并且在外部SELECT
中不需要GROUP BY
。参见:
6fe3ivhb2#
为了说明,
重要行是
GROUP BY MAIN_TABLE
,它将处理来自SOME_TABLE
的NULL值字符串