交叉连接到 DQL

问题描述 投票:0回答:2

我正在尝试将这个我认为简单的 mysql 查询转换为 Doctrine dql,但是,我现在经历了相当大的斗争......

SELECT (c.prix-aggregates.AVG) AS test 
FROM immobilier_ad_blank c 
CROSS JOIN (
     SELECT AVG(prix) AS AVG 
     FROM immobilier_ad_blank) 
AS aggregates

这样做的目的:创建 z 分数。 原始实现来自这个问题Calculate Z-Score for every row in MySQL? (简单)

我考虑过在实体内创建一个关联,但我的意思是它没有必要,它仅用于统计。

编辑:顺便说一句,我不想使用原始 SQL,我将使用

getDQL
从另一个查询生成器表达式中提取“子查询”。否则,我将不得不重写我的动态查询构建器以考虑 rawSQL。

编辑2: 试过这个

$subQb = $this->_em->createQueryBuilder();
$subQb->addSelect("AVG(subC.prix) as AMEAN")
      ->from("MomoaIntegrationBundle:sources\Common", "subC");
$subDql = $subQb->getDQL();

$dql = "SELECT c.prix FROM MomoaIntegrationBundle:sources\Common c INNER JOIN ($subDql) AS aggregates";

原始 dql 是:

SELECT c.prix FROM MomoaIntegrationBundle:sources\Common c INNER JOIN (SELECT AVG(subC.prix) as AMEAN FROM MomoaIntegrationBundle:sources\Common subC) AS aggregates

收到这个奇怪的错误:

line 0, col 70 near '(SELECT AVG(subC.prix)': Error: Class '(' is not defined.

编辑3: 我发现了一种鹰派的方式来使其发挥作用,但学说在实体等的实施方面很顽固,并且忘记了统计不需要实体!

     $subQb = $this->_em->createQueryBuilder();
    $subQb->addSelect("AVG(subC.prix) as AMEAN")
            ->from("MomoaIntegrationBundle:sources\Common", "subC");

    $sql = "SELECT (c.prix-aggregates.sclr_0) AS test FROM immobilier_ad_blank c CROSS JOIN "
            . "({$subQb->getQuery()->getSQL()}) AS aggregates";
    $stm = $stm = $this->_em->getConnection()->prepare($sql);
    $stm->execute();
    $data = $stm->fetchAll();

如果您有更好的解决方案,我洗耳恭听!我实际上不喜欢这个解决方案。

php mysql symfony doctrine-orm
2个回答
1
投票

从 Doctrine 2.4 开始,可以在不使用定义的关联的情况下进行 JOIN,例如:

SELECT u FROM User u JOIN Items i WITH u.age = i.price

这个没有任何意义,但你明白了。 在这种情况下,

WITH
关键字是绝对必需的,否则会出现语法错误,但您可以只提供一个虚拟条件,如下所示:

SELECT u FROM User u JOIN Items i WITH 0 = 0

这本质上会导致交叉连接。 在特定情况下这是否是一个好主意是一个不同的问题,但我遇到过这确实非常有用的情况。

编辑:我现在使用的是Doctrine 2.19,在这种情况下,

WITH
关键字现在也是可选的。 这意味着现在可以简单地写
SELECT u FROM User u JOIN Items i


0
投票

对于复杂查询,您可能需要考虑绕过 DQL 并使用本机查询 - 特别是因为您不需要实体中的结果。

$connection = $em->getConnection();

$statement = $connection->prepare("
    select c.prix-aggregates, t1.avg 
    from immobilier_ad_blank
    cross join (
        select avg(prix) as avg
        from immobilier_ad_blank
    ) t1
");

$statement->execute();

$results = $statement->fetchAll();
© www.soinside.com 2019 - 2024. All rights reserved.