実稼働の MySQL DB を Postgres に変換する必要性を受け継いでいます。これは、テーブル/関数の作成に単純な SQL ステートメントを使用して (Navicat を使用して半自動変換を生成する) 問題なく処理されましたが、やや複雑なビューの変換で問題が発生しています。
調査によると、これは 2 つの 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 のソリューションはどちらも機能します。ここでの私の役割は、システムを「現状のまま」変換することであるため、ここではパトリックを支持します。将来的にはリファクタリングの余地があるかもしれませんが、この段階では、他の誰かのダクトテープソリューションを台無しにする (または改善する) のは危険だと感じています (つまり、コードベースは、ドキュメントの兆候がなく、場所によっては過度に複雑に見えます。ビジネス ロジックに関する背景情報がなければ、いろいろ調べたり、コアの改善を試みたりすることに消極的です)。いずれにせよ、モデルの一部をオーバーホールする必要があるのではないかと思うので、[原文のまま]-ここでは修正を優先します。
いくつかのクリック操作が元のクエリを生成した可能性があると思いました...元の開発者に疑いの利益を与えようとし、迅速な(つまり、面倒な)ターンアラウンドを必要とするビジネス上の圧力があったと想定しました。複雑な SQL は私の得意分野ではありませんが、私の直感が正しかったことをうれしく思います。クエリはそもそも不要で複雑です。おそらく、ビューは計画外のボルトオンでした-そもそも設計されていません. 賢明であろうとなかろうと、私はおそらく ORM ベースのアプローチで問題を解決しようとしたでしょう。
私は土壇場でこのプロジェクトに参加し、再起動のためにクリーンアップを実行しています (元の開発者は「手放しました」)。いわば空挺部隊を実行しています。ありがたいことに、このビューの問題はパズルの最後のピースに現れます。ありがとうございました :-)