postgresql 如何将HAVING应用于别名

svmlkihl  于 2023-04-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(187)

我有一个查询,它会像这样动态地创建一个列:

SELECT 
v_list_client.id AS "id",
EXISTS(
  SELECT id FROM message 
  WHERE to_phone_number = v_list_client."phoneNumber" 
    AND  created_by_agent_id != 
  (SELECT id FROM agent WHERE agent_role_id = (
    SELECT id FROM agent_role WHERE label = 'Bot'))
) AS "hasReceivedMessageFromAgent",
*
FROM v_list_client
LEFT JOIN v_form
ON (v_form."client" ->> 'id')::integer = id
WHERE (v_form."formTypeId")::integer = 1
AND (v_form."isReceived")::boolean = true
HAVING "hasReceivedMessageFromAgent" = true

我希望HAVING子句只在客户端收到来自代理的消息时返回结果。即hasReceivedMessageFromAgent列为true

r7knjye2

r7knjye21#

HAVING仅适用于GROUP BY之后。但是也不能在WHERE子句中引用输出列。(这就是你在错误的树。)参见:

  • PostgreSQL Where count条件

从结果中删除"hasReceivedMessageFromAgent"列。根据定义,它将始终是真的,因此是噪声。您确实希望在另一个WHERE子句中使用表达式作为筛选器。
我怀疑你的问题更多。特别是agent上的子查询看起来可能会返回多行,这将引发异常。参见:

  • Postgres错误:用作表达式的子查询返回多行

考虑这个重写:

SELECT *
FROM   v_list_client l
JOIN   v_form        f ON (f.client ->> 'id')::int = l.id  -- was a fake LEFT JOIN
WHERE  f."formTypeId"::int = 1  -- why the need to cast?
AND    f."isReceived"::boolean  -- why the need to cast?
AND    EXISTS (
   SELECT FROM message m
   LEFT   JOIN (agent a JOIN agent_role ar ON ar.label = 'Bot' AND ar.id = a.agent_role_id) ON a.id = m.created_by_agent_id
   WHERE  m.to_phone_number = l."phoneNumber" 
   AND    a.id IS NULL
   );

关于假LEFT JOIN,见:

  • 使用LEFT JOIN的查询不返回计数为0的行

"formTypeId"应该已经是integer
"isReceived"应该已经是boolean
两者的演员阵容都是昂贵的废话。如果值始终有效,则列应已具有正确的数据类型。如果不是这样的话,那就失败了。
旁白:如果可能的话,在Postgres中使用法律的的、小写的、未加引号的标识符。参见:

  • PostgreSQL列名区分大小写吗?

相关问题