将具有自定义列和特定于rdbms的函数的复杂SQL查询转换为Doctrine

时间:2017-06-19 14:51:34

标签: postgresql doctrine-orm orm propel

我多年来一直是Propel用户,最近才开始转向Doctrine。对我来说这仍然是一个新生事物,有时Propel的习惯会让我难以“思考”。以下是具体案例。 你不必知道Propel回答我的问题 - 我也用原始SQL提出我的案例。

我的查询引用的表的简化结构如下:

  • 应用程序表具有FK到Admin,其具有FK到用户(DB中的fos_user)
  • ApplicationUser表具有FK到应用程序

我的查询获取所有应用程序记录,其中包含从相关用户记录(通过Admin)检索的其他信息的自定义列以及相关ApplicationUser对象的一些COUNT,其中一个还被过滤(adminnameusercountusercountperiod列已添加到查询中。

我有一个像这样的Propel查询:

ApplicationQuery::create()
->leftJoinApplicationUser()
->useAdminQuery()
    ->leftJoinUser()
->endUse()
->withColumn('fos_user.username', 'adminname')
->withColumn('COUNT(application_user.id)', 'usercount')
->withColumn('COUNT(application_user.id) FILTER '
    . '(WHERE score > 0 AND '
    . ' application_user.created_at >= to_timestamp('.strtotime($users_scored['begin']).') and '
    . ' application_user.created_at < to_timestamp('.strtotime($users_scored['end']).') )', 'usercountperiod')
->groupById()
->groupBy('User.Id')
->orderById('DESC') 
->paginate( ....

这是它转换为SQL(PostgreSQL)的方式:

SELECT application.id, application.name, ..., 
    fos_user.username AS "adminname",
    COUNT(socialscore_application_user.id) AS "usercount", 
    COUNT(application_user.id) FILTER (
        WHERE score > 0 AND 
            application_user.created_at >= to_timestamp(1491004800) and 
            application_user.created_at < to_timestamp(1498780800) ) AS "usercountperiod" 
FROM application 
    LEFT JOIN application_user ON (application.id=application_user.application_id) 
    LEFT JOIN admin ON (application.admin_id=admin.id) 
    LEFT JOIN fos_user ON (admin.id=fos_user.id) 
    GROUP BY application.id,fos_user.id 
    ORDER BY application.id DESC
    LIMIT 15

正如你所看到的那样,它非常复杂(就将它翻译成Doctrine ORM而言,当你是像我这样的Doctrine新手:))。它使用PostgreSQL的特定功能:

  • 能够在GROUP BY语句中只包含主键,而同一个表中的其他列可以在SELECT中使用,而不会聚合函数或包含在GROUP BY中(因为它们“依赖于”PK);
  • FILTER,允许您进一步过滤输入聚合函数的记录

它还会使用一些连接并添加自定义列(adminnameusercountusercountperiod),我可以在生成的Propel模型对象中访问这些列(具有$result->getAdminname()等功能

我的问题是:尽可能简单地实现尽可能类似的“Doctrine方式”(使用一些PostgreSQL特定的或任何特定于RDBMS的功能,添加一些自定义列,可以通过ORM对象访问等等吗?

感谢您的帮助。

0 个答案:

没有答案