cakephp 查询生成器:对关联数据使用多个SUM的子查询

vuktfyat  于 2022-11-11  发布在  PHP
关注(0)|答案(2)|浏览(233)

我想请求一个方法的建议,使用查询构建器,以获得多个总和从相关的模型。
有三个表:

invoices    invoice_items                               payment_receipts
--------    -------------                               -------------
id | name   id| invoice_id  | invoice_qty   unit_price  id| invoice_id  | receipt_amount
===|======  ==========================================  ================================    
 1 |INV01   1| 1            | 1300          |12.00      1 | 1           | 1000
 2 |INV02   2| 1            | 2600          |9.00       2 | 1           | 2000
 3 |INV03   3| 2            | 1100          |15.00      3 | 3           | 900
            4| 3            | 900           |12:00

对于每张发票,我需要项目总金额(数量 * 价格)的总和,以及付款收据的总和。
此查询(包含子查询)正确地获得了我要查找的结果:

SELECT Invoices.id, Invoices.invoice_name, InvoiceItemSum.SumOfAmount, PaymentSum.SumOfPaymentAmount
  FROM Invoices
  INNER JOIN (
    SELECT invoice_id, SUM(Invoice_items.invoice_qty * Invoice_items.unit_price) AS SumOfAmount
      FROM Invoice_items
      GROUP BY Invoice_id
  ) InvoiceItemSum ON InvoiceItemSum.Invoice_id = Invoices.id
  LEFT JOIN (
    SELECT Invoice_id, SUM(Payment_receipts.receipt_amount) AS SumOfPaymentAmount
    FROM Payment_receipts
    GROUP BY Invoice_id
  ) PaymentSum ON PaymentSum.Invoice_id = Invoices.id
WHERE Invoices.invoice_id = 33

我可以直接在我的CakePhp应用程序中执行这个查询,并得到我需要的结果,所以它是这样工作的。
然而,我想通过查询构建器获得一个更优雅的CakePHP方法的建议。
我已经试过了:

$query = $this->Invoices->find()->contain(['InvoiceItems', 'PaymentReceipts']);
        $query->select([
                'Invoices.id',
                'Invoices.invoice_name',
            ]);
        $query->select([
            'total_inv_amt' => $query->func()->sum('InvoiceItems.invoice_qty * InvoiceItems.unit_price'),
            'total_paid_amt' => $query->func()->sum('PaymentReceipts.receipt_amount')
                ])
                ->innerJoinWith('InvoiceItems')
                ->leftJoinWith('PaymentReceipts')
                ->group(['Invoices.id']);
        $query->where(['Invoices.id' => 33]);

但是,通过创建以下查询,这会导致两个总和加倍:

SELECT 
  Invoices.id AS Invoices__id, 
  Invoices.invoice_name AS Invoices__invoice_name, 
  (
    SUM(
      InvoiceItems.invoice_qty * InvoiceItems.unit_price
    )
  ) AS total_inv_amt, 
  (
    SUM(PaymentReceipts.receipt_amount)
  ) AS total_paid_amt 
FROM 
  invoices Invoices 
  INNER JOIN invoice_items InvoiceItems ON Invoices.id = (InvoiceItems.invoice_id) 
  LEFT JOIN payment_receipts PaymentReceipts ON Invoices.id = (PaymentReceipts.invoice_id) 
WHERE 
  Invoices.id = 33 
GROUP BY 
  Invoices.id

我已经尝试过按照文档进行子查询,但都没有成功。我也尝试过连接,但仍然没有成功。
我的问题是:使用查询构建器编写此查询的好方法是什么?
提前感谢您的任何建议!

bvn4nwqk

bvn4nwqk1#

你可以通过cakephp JOIN很容易地做到这一点。检查这个解决方案,它可能会帮助你。直接写在编辑器,不保证没有语法错误!

$this->Invoices->find()
   ->select([
               'Invoices.id',
               'Invoices.invoice_name',
               'total_inv_amt' => $query->func()->sum('InvoiceItems.invoice_qty * InvoiceItems.unit_price'),
               'total_paid_amt' => $query->func()->sum('PaymentReceipts.receipt_amount')
    ])
    ->join([
            'table' => 'InvoiceItems',
            'alias' => 'InvoiceItems',
            'type' => 'Inner',
            'conditions' => [
                 // your condition for InvoiceItems
             ],
    ])
    ->join([
            'table' => 'PaymentReceipts',
            'alias' => 'PaymentReceipts',
            'type' => 'LEFT',
            'conditions' => [
                // condition for PaymentReceipts
            ],
    ])
ndh0cuux

ndh0cuux2#

最后,在回顾了Alimon的答案和其他几个关于子查询的问题(如this和this)之后,我得出了正确的Query Builder解决方案。

$subquery_a = $this->Invoices->InvoiceItems->find('all');
        $subquery_a
            ->select(['totalinvoiceamt' => $subquery_a->func()->sum('invoice_qty * unit_price') ])
            ->where([
                'InvoiceItems.invoice_id = Invoices.id'
            ]);

        $subquery_b = $this->Invoices->PaymentReceipts->find('all');
        $subquery_b
            ->select(['totalpaymentamt' => $subquery_b->func()->sum('receipt_amount') ])
            ->where([
                'PaymentReceipts.invoice_id = Invoices.id'
            ]);

        $query = $this->Invoices->find('all')
            ->select([
            'Invoices.id',
            'Invoices.invoice_name',
            'InvoiceItems__total_invoice_amount' => $subquery_a,
            'PaymentReceipts__total_payments_amount' => $subquery_b
            ])
            ->join([
                [
                    'table'     => 'invoice_items',
                    'alias'     => 'InvoiceItems',
                    'type'      => 'INNER',
                    'conditions'=> [
                        'Invoices.id = InvoiceItems.invoice_id'
                    ]
                ]
            ])
            ->join([
                [
                    'table'     => 'payment_receipts',
                    'alias'     => 'PaymentReceipts',
                    'type'      => 'LEFT',
                    'conditions'=> [
                        'Invoices.id = PaymentReceipts.invoice_id'
                    ]
                ]
            ])
            ->group('InvoiceItems.invoice_id');
            $query->where(['Invoices.id' => 33]);

结果与直接查询相同,虽然SQL看起来与手动查询稍有不同,但结果相同。
感谢Alimon等人的帮助。

相关问题