我继承了将生产 MySQL DB 转换为 Postgres 的需要。这主要是使用简单的 SQL 语句来创建表/函数(使用 Navicat 生成半自动转换)来处理的,但现在我在转换有点复杂的视图时遇到了问题。
研究表明,这可能是由于两个 DB 处理子查询(WHERE 语句)的方式不同,也许这只是语法上的差异。这里的业务逻辑是未知的,因为代码库是从另一个开发人员那里继承的。
运行以下命令(使用 Laravel 迁移/PHP 脚本):
SELECT
parent.is_owner AS is_owner,
parent.brand AS first_name,
parent.id AS id,
(SELECT count(c.id)
FROM campaigns c
WHERE((
(c.user_id = parent.id)
OR
(c.user_id = child.id)
)
AND
(c.campaign_status_id = 4)
))
AS current_campaigns,
(SELECT count(c.id)
FROM campaigns c
WHERE
((
(c.user_id = parent.id)
OR (c.user_id = child.id)
)
AND (c.campaign_status_id = 5)
))
AS past_campaigns,
(SELECT count(c.id)
FROM campaigns c
WHERE
((
(c.user_id = parent.id)
OR (c.user_id = child.id))
AND (c.campaign_status_id = 2)
))
AS pending_campaigns,
(SELECT count(c.id)
FROM campaigns c
WHERE ((
(c.user_id = parent.id)
OR (c.user_id = child.id)
)
AND (c.invoice_status = '1')
))
AS past_invoices
FROM ((users parent LEFT JOIN campaigns mc ON
((parent.id = mc.user_id)))
LEFT JOIN users child ON ((child.parent_owner = parent.id)
))
WHERE
(
(parent.is_owner = 1)
OR (child.is_retailer = 1)
)
GROUP BY parent.id
ORDER BY parent.brand
...触发错误
SQLSTATE[42803]: Grouping error: 7 ERROR: subquery uses ungrouped column "child.id" from outer query
LINE 1: ...c where (((c.user_id = parent.id) or (c.user_id = child.id)) ...
谁能建议如何格式化这个以便 Postgres 运行子查询?
顺便说一句,这里在 Laravel 迁移脚本中使用的 PHP 代码是:
...
DB::unprepared("CREATE VIEW client AS
select parent.is_owner AS is_owner,parent.brand AS first_name,parent.id AS id
,(select count(c.id) from campaigns c where (((c.user_id = parent.id) or (c.user_id = child.id)) and (c.campaign_status_id = 4))) AS current_campaigns
,(select count(c.id) from campaigns c where (((c.user_id = parent.id) or (c.user_id = child.id)) and (c.campaign_status_id = 5))) AS past_campaigns
,(select count(c.id) from campaigns c where (((c.user_id = parent.id) or (c.user_id = child.id)) and (c.campaign_status_id = 2))) AS pending_campaigns
,(select count(c.id) from campaigns c where (((c.user_id = parent.id) or (c.user_id = child.id)) and (c.invoice_status = '1'))) AS past_invoices
from ((users parent
left join campaigns mc on((parent.id = mc.user_id)))
left join users child on((child.parent_owner = parent.id)))
where ((parent.is_owner = 1) or (child.is_retailer = 1))
group by parent.id
order by parent.brand;");
更新,固定:
杰出的。来自所有人的非常好的输入。
@patrick 和 @ErwinBrandstetter 的解决方案都有效。我会支持帕特里克在这里,因为我的角色是“按原样”转换系统。未来可能会有重构的空间,但在这个阶段,我觉得弄乱(或改进)别人的管道胶带解决方案是有风险的(即代码库在某些地方似乎过于复杂,没有文档的迹象,我在没有更多关于业务逻辑的背景信息的情况下,我不愿意四处寻找或尝试核心改进)。我怀疑模型的某些部分可能无论如何都需要大修,所以[原文如此]-fix 在这里受到青睐。
我怀疑一些点击抖动可能已经生成了原始查询......试图让原始开发人员从怀疑中受益,并假设存在一些需要快速(即鼠标)周转的业务压力。复杂的 SQL 不是我的强项,但我很高兴我的直觉是正确的,查询一开始就没有必要复杂。也许这个视图是一个计划外的螺栓 - 不是一开始就设计的。明智与否,我可能会尝试使用基于 ORM 的方法来解决问题。
我最后一分钟在这个项目上,运行清理以重新启动(原始开发是“放手”),所以我正在使用一个充满未知功能的大部分未记录的代码库。像伞兵一样奔跑。值得庆幸的是,这个视图问题出现在拼图的最后一块。谢谢 :-)