Как избежать двойного вычисления полей в представлении MariaDB

У меня есть следующее представление в 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

Есть ли способ избежать двойного расчета кредита и дебета баланса?

Если версия вашего сервера поддерживает CTE (10.2.2 или выше), используйте ее. С другой стороны, это скалярные вычисления, которые выполняются достаточно быстро. ПС. Также в (.. UNION .. UNION ..) используйте UNION DISTINCT в качестве последнего оператора и UNION ALL как все вышеперечисленные, что улучшится за счет уменьшения количества сортировок.

Akina 06.05.2024 08:50

Имейте в виду (также для подобных случаев в будущем) о проблеме, которая вызвала МНОГО ошибок в мире (потому что иногда могут пройти месяцы, прежде чем она всплывет): порядок оценки и присвоения @variables не определен в MySQL, поэтому у вас нет гарантии, что определение @Credit будет выполнено до его использования! Вероятно, так и будет... пока этого не произойдет...

Roemer 06.05.2024 12:33
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
2
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
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.

Rick James 06.05.2024 20:57

@RickJames Не стандартно, но работает с mysql/mariadb

yotheguitou 06.05.2024 21:03

Умный клодж! Наверное, стоит проверить, насколько это на самом деле быстрее.

Rick James 06.05.2024 23:09

Я предполагаю, что это не намного быстрее, чем просто наличие третьего «если», хотя, возможно, заметно медленнее.

ysth 07.05.2024 17:42

Другие вопросы по теме