У меня есть следующее представление в mariadb
, которое показывает кредит, дебет и баланс акций:
SELECT pitem,
Bdate,
credit,
debit,
sum(ifnull(bal, 0)) OVER (PARTITION BY pitem ORDER BY bdate, DESC1) balance,
DESC1
FROM (
SELECT a.Pitem,
a.Bdate,
a.Trn,
If((trn=1 AND a.qty>0), a.Qty, 0) AS Credit,
If(trn=0 OR a.qty<0, abs(a.Qty), 0) AS Debit,
(If((trn=1 AND a.qty>0), a.Qty, 0)) - (If(trn=0 OR a.qty<0, abs(a.Qty), 0)) AS Bal,
a.Desc1
FROM (
SELECT tblphmrefill.RfItem AS PItem,
tblphmrefill.rfDate AS BDate,
tblphmrefill.rfQty AS Qty,
CONCAT(
if (rfqty>0, 'Purchase No_', 'Discard_BMW_'),
coalesce(tblphmrefill.RfInvoice, 0), '_Vend_', rfsuppID
) AS DESC1,
1 AS Trn
FROM tblphmrefill
UNION (
SELECT invoicerefundphm.phmItem AS pItem,
invoice.Bdate,
invoicerefundphm.Qty,
CONCAT('Refund_', billno, '_', invoice.BName) AS DESC1,
1 AS Trn
FROM invoice
)
INNER JOIN invoicerefundphm
ON invoice.BilID = invoicerefundphm.Billno
UNION (
SELECT invoicephm.phmItem AS PItem,
invoice.BDate,
invoicephm.Qty,
CONCAT('Sales_', billno, '_', invoice.BName),
0 AS Trn
FROM invoicephm
INNER JOIN invoice
ON invoicephm.Billno = invoice.BilID
ORDER BY invoice.bdate, invoice.bilid ASC
)
) AS a
) phmtbatch_int
Order by Bdate, DESC1 Asc
Проблема в этой части:
SELECT a.Pitem,
a.Bdate,
a.Trn,
If((trn=1 AND a.qty>0), a.Qty, 0) AS Credit,
If(trn=0 OR a.qty<0, abs(a.Qty), 0) AS Debit,
(If((trn=1 AND a.qty>0), a.Qty, 0)) - (If(trn=0 OR a.qty<0, abs(a.Qty), 0)) AS Bal,
a.Desc1
здесь код рассчитывает баланс, но выполняет один и тот же расчет дважды.
Я попробовал следующее:
SELECT a.Pitem,
a.Bdate,
a.Trn,
@Credit := (If((trn=1 AND a.qty>0), a.Qty, 0)) AS Credit,
@Debit := (If(trn=0 OR a.qty<0, abs(a.Qty), 0)) AS Debit,
(@Credit - @Debit) AS Bal,
a.Desc1
Но Мариадб высказывает error 1351
высказывание
view contains variable or parameter which is not allowed
Есть ли способ избежать двойного расчета кредита и дебета баланса?
Имейте в виду (также для подобных случаев в будущем) о проблеме, которая вызвала МНОГО ошибок в мире (потому что иногда могут пройти месяцы, прежде чем она всплывет): порядок оценки и присвоения @variables
не определен в MySQL, поэтому у вас нет гарантии, что определение @Credit будет выполнено до его использования! Вероятно, так и будет... пока этого не произойдет...
SELECT a.Pitem,
a.Bdate,
a.Trn,
If((trn=1 AND a.qty>0), a.Qty, 0) AS Credit,
If(trn=0 OR a.qty<0, abs(a.Qty), 0) AS Debit,
(SELECT Credit - Debit) AS Bal,
a.Desc1
Это действительно работает? Credit
не должен быть доступен до GROUP BY
, HAVING
и ORDER BY
.
@RickJames Не стандартно, но работает с mysql/mariadb
Умный клодж! Наверное, стоит проверить, насколько это на самом деле быстрее.
Я предполагаю, что это не намного быстрее, чем просто наличие третьего «если», хотя, возможно, заметно медленнее.
Если версия вашего сервера поддерживает CTE (10.2.2 или выше), используйте ее. С другой стороны, это скалярные вычисления, которые выполняются достаточно быстро. ПС. Также в (.. UNION .. UNION ..) используйте UNION DISTINCT в качестве последнего оператора и UNION ALL как все вышеперечисленные, что улучшится за счет уменьшения количества сортировок.