【发布时间】:2015-10-07 23:04:43
【问题描述】:
我继承了将生产 MySQL 数据库转换为 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 的方法来解决问题。
我在最后一分钟参与了这个项目,正在运行清理以重新启动(原始开发人员是“放手”),所以我正在使用一个几乎没有记录的代码库,其中充满了未知的功能。像伞兵一样奔跑。值得庆幸的是,这个视图问题出现到了拼图的最后一块。谢谢你:-)
【问题讨论】:
-
这里的问题是,与 MySQL 不同,PostgreSQL 实际上遵循 SQL 标准。这意味着如果您进行分组,则所有列都需要在分组中或需要聚合(最小/最大/平均/等)函数。如果您可以将表定义和少量示例数据添加到 sqlfiddle,我可以轻松地为您创建查询:)
-
我在任何地方都没有看到您的 Postgres 版本?确定最佳答案至关重要。此外,该错误是由于查询中的歧义造成的,并且您没有提供解决方法的信息。基本上:您想计算与多个孩子相关联的广告系列多次还是一次?
-
祝您重新启动顺利,并保持您的手指交叉。 +1 提出恰当的问题和后续行动。
标签: mysql sql postgresql laravel-migrations