我有以下查询:
query =
"SELECT
data #>> '{id}' AS id,
data #>> '{name}' AS name,
data #>> '{curator}' AS curator,
data #> '{$isValid}' AS \"$isValid\",
data #> '{customer}' AS customer,
data #> '{$createdTS}' AS \"$createdTS\",
data #> '{$updatedTS}' AS \"$updatedTS\",
data #> '{$isComplete}' AS \"$isComplete\",
(count(keys))::numeric as \"numProducts\",
created_at
FROM
appointment_intakes,
LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN
appointment_intake_users
ON
appointment_intake_users.appointment_intake_id = appointment_intakes.id
#{where_clause}
GROUP BY id"
它导致以下错误:
对表“appointment_intakes”
的FROM子句条目的无效引用
我添加后错误开始发生:
LATERAL jsonb_object_keys(data #> '{products}') keys
和
(count(keys))::numeric as \"numProducts\"
因为我需要计算产品数量。
如何避免此错误发生?
答案 0 :(得分:4)
错误消息的直接原因是任何明确的JOIN
绑定强于逗号(,
),否则等同于CROSS JOIN
,但是(per documentation ):
注意:后者的等效性在两个以上时并不完全相同 表格出现,因为
JOIN
比逗号绑定得更紧密。例如FROM T1 CROSS JOIN T2 INNER JOIN T3 ON condition
与...不一样FROM T1, T2 INNER JOIN T3 ON condition
,因为condition
可以 在第一种情况下引用T1
但不是第二种情况。
最后强调我的。这完全是您错误的原因。您可以修复它:
FROM appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...
但这不是查询中唯一的问题。见下文。
有人可能会争辩说,Postgres应该看到LATERAL
只对左边的表格有意义。但是试图快速变聪明会让你陷入困境。最好严格要求。
我添加了表别名和表限定的所有列名称。在此期间,我简化了JSON参考并修剪了一些噪音。 该查询 仍然不正确 :
"SELECT i.data ->> 'id' AS id,
i.data ->> 'name' AS name,
i.data ->> 'curator' AS curator,
i.data -> '$isValid' AS \"$isValid\",
i.data -> 'customer' AS customer,
i.data -> '$createdTS' AS \"$createdTS\",
i.data -> '$updatedTS' AS \"$updatedTS\",
i.data -> '$isComplete' AS \"$isComplete\",
count(k.keys)::numeric AS \"numProducts\",
u.created_at
FROM appointment_intakes i
, jsonb_object_keys(i.data -> 'products') AS k(keys)
JOIN appointment_intake_users u ON u.appointment_intake_id = i.id
#{where_clause}
GROUP BY i.id"
如果这是正确的并且基于一些更多的假设,解决方案可能是在子查询中进行计数,例如:
基于以上假设:
SELECT i.data ->> 'id' AS id,
i.data ->> 'name' AS name,
i.data ->> 'curator' AS curator,
i.data -> '$isValid' AS "$isValid",
i.data -> 'customer' AS customer,
i.data -> '$createdTS' AS "$createdTS",
i.data -> '$updatedTS' AS "$updatedTS",
i.data -> '$isComplete' AS "$isComplete",
(SELECT count(*)::numeric
FROM jsonb_object_keys(i.data -> 'products')) AS "numProducts",
min(u.created_at) AS created_at
FROM appointment_intakes i
JOIN appointment_intake_users u ON u.appointment_intake_id = i.id
-- #{where_clause}
GROUP BY i.id
由于您只需要计数,我将您的LATERAL
联接转换为相关子查询,从而避免了由多个1:n联接组合而产生的各种问题。更多:
您 需要 正确转义标识符,使用预处理语句并将值作为值传递。不要将值连接到查询字符串中。这是对随机错误或 SQL注入攻击的邀请。
以下是PHP的最新示例: