【问题标题】:Sql to Dql using Where Not In or Not ExistsSql 到 Dql 使用 Where Not In 或 Not Exists
【发布时间】:2018-01-08 19:17:08
【问题描述】:

我正在尝试查找发票 ID 未出现在具有某些参数的另一个表中的发票列表。这个问题整天困扰着我。我尝试过不存在和不存在的变体。

这是我最终想要实现的 sql:

SELECT * FROM invoices 
JOIN invoiceitem 
WHERE invoiceitem.class = 'ITEM' 
AND invoices.rmlist >= $date1 
AND invoices.rmlist <= $date2 
AND NOT EXISTS (
SELECT * FROM invoice_history 
WHERE invoices.id = invoice_history.invid 
AND invoice_history.ttype = 'PR' 
AND invoice_history.note = 'Vouchers Printed') 
AND invoiceitem.voucherrequired = 1 
GROUP BY invoices.id 
ORDER BY invoices.depdate ASC

根据我所学到的试图弄清楚这一点,dql 中没有“不存在”(不要引用我的话),所以我一直在尝试使用“不存在”方法。从本质上讲,这就是我所有努力的结果:

$q2 = $em->createQueryBuilder()
                    ->from('ClicctTravelBundle:InvoiceHistory', 'ih')
                    ->Where("ih.ttype = 'PR'")
                    ->andWhere("ih.note = 'Vouchers Printed'")
                    ->groupBy('ih.invid');

                $qb->leftJoin('i.history', 'h')
                    ->where($qb->expr()->notExist('i.id', $q2->select('ih.invid')->getDQL()));

我做错了什么?感谢您的帮助!

[编辑]
我相信我已经解决了我的问题。这段代码似乎对我有用:

$qb = $em->createQueryBuilder()
        ->from('ClicctTravelBundle:Invoices', 'i')
        ->join('i.invoiceitems', 'b')          
        ->select('i')
        ->Where("b.class = 'ITEM'")
        ->andWhere("i.rmlist >=:fdate")
        ->setParameter("fdate",$fromdate)
        ->andWhere("i.rmlist <=:tdate")
        ->setParameter("tdate",$todate)
        ->orderBy('i.depdate')
        ->groupBy('b.invoiceno');

$qb2 = $em->createQueryBuilder()
                ->select("h")
                ->from("ClicctTravelBundle:InvoiceHistory","h")
                ->andWhere("h.invid = i.id")
                ->andWhere("h.note = 'Vouchers Printed'");

            $qb->andWhere($qb->expr()->not($qb->expr()->exists($qb2->getDQL())));

感谢大家的帮助!

【问题讨论】:

  • 我不知道 DQL,所以我不确定你会怎么做,但我一直发现 NOT INs 效率非常低。如果您可以修改您的查询,一个更高效的方法是执行SELECT a.id FROM a LEFT OUTER JOIN b ON a.id = b.id WHERE b.id IS NULL。这在功能上与NOT IN 相同,但允许优化器制定更好的查询计划。
  • 感谢您的反馈。它似乎正在工作,但我在添加其他参数时遇到了麻烦。无论我尝试什么,我都会不断收到语法错误。 SELECT * FROM invoices JOIN invoiceitem WHERE invoiceitem.class= 'ITEM' LEFT OUTER JOIN invoice_history ON invoices.id = invoice_history.invid WHERE invoice_history.invid IS NULL 给我一个语法错误。
  • @Shawn 抱歉忘记给你加标签
  • 我不确定 DQL 是否可以进行这样的 JOIN。虽然我不明白为什么它不能。由于这样的原因,我不是 ORM 的忠实粉丝。这应该是一个相对简单的查询,但是 ORM 使它变得更复杂一些。 :-/

标签: sql dql not-exists notin


【解决方案1】:

你的加入没有加入条件,我加了一个。通过将 0 与计数进行比较,您可以获得与 NOT EXISTS 相同的效果。此外,不属于 GROUP BY 的所有列都必须应用聚合函数。

  SELECT invoices.id, max(invoices.depdate) as depdate
    FROM invoices JOIN invoiceitem ON (invoices.id= invoiceitem.id)
   WHERE invoiceitem.class = 'ITEM'
     AND invoices.rmlist >= $date1
     AND invoices.rmlist <= $date2
     AND 0 = 
             (SELECT count(*) c
                FROM invoice_history
               WHERE invoices.id = invoice_history.invid
                 AND invoice_history.ttype = 'PR'
                 AND invoice_history.note = 'Vouchers Printed')
     AND invoiceitem.voucherrequired = 1
GROUP BY invoices.id
ORDER BY depdate ASC

【讨论】:

  • 嗯。这个 sql 查询似乎为我返回 0 个结果。真的很感谢你的帮助。我问题中的 sql 实际上给了我正在寻找的正确结果。我只需要把它变成dql。
猜你喜欢
  • 2016-02-11
  • 1970-01-01
  • 2013-04-17
  • 2015-07-06
  • 2016-05-19
  • 2021-05-29
  • 2015-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多