firebird 1.5, агрегатные функции и HAVING

Alexos

Новичок
firebird 1.5, агрегатные функции и HAVING

Заимелся я что то со следующей задачей..
Есть таблица клиентов CLIENTS..
Есть таблица клиентских заказов ZAKAZ (с полем для суммы долга по заказу)..
Есть таблица всех клиентских платежей KASSA..
Необходимо вывести всех клиентов, у которых сумма всех платежей обязательно с маркером "Т" и "31" (таблица KASSA) минус сумма всех его долгов по всем его заказам (таблица ZAKAZ) не равнялась бы нулю!!!
Проще говоря, вывод должников определенной категории!!!

PHP:
SELECT CLIENTS.CLIENT_ID,
             CLIENTS.FIO,

             SUM(ZAKAZ.UNRDOLG * ZAKAZ.CUR_CURS) as SUM_DOLGA_Z,              // сумма долга по всем заказам
             SUM(KASSA.OPSUMM * KASSA.OPCURCURS) AS OPSUMM                    // сумма сумма всех платежей

             FROM CLIENTS
               LEFT JOIN ZAKAZ ON (ZAKAZ.CLIENT_ID=CLIENTS.CLIENT_ID)
               LEFT JOIN KASSA ON (KASSA.OPKONTRA=CLIENTS.FIO)
                    WHERE ZAKAZ.UNRDOLG <> 0
                    AND KASSA.OPSTAT = 31
                    AND KASSA.KASSA_AUTOGEN='T'
                    GROUP BY CLIENTS.CLIENT_ID, CLIENTS.FIO
                    HAVING (SUM(KASSA.OPSUMM * KASSA.OPCURCURS) - SUM(ZAKAZ.UNRDOLG * ZAKAZ.CUR_CURS)) <> 0
                    ORDER BY CLIENTS.FIO ASC
Результат таков - долго думаем и ничего не выводим..
 

autosoft

Новичок
1. При чём тут PHP ?

2. Что такое KASSA.OPKONTRA=CLIENTS.FIO ? Почему не задействовать здесь CLIENT_ID ?

3. Что-бы избежать дублирований при пересечении строк таблиц ZAKAZ и KASSA нужно использовать внешнее соединение строк таблицы CLIENT со строками других таблиц, что и сделано. Но, это повышает требования ко времи выполнения запроса и к ресурсам необходимым сервуру для этого - серверу нужно много памяти для выполнения такого запроса. Поэтому внешних соединений таблиц вообще нужно избегать по возможности.

4. Создать процедуру:
PHP:
CREATE PROCEDURE GET_CLIENTS (

    OPSTAT INTEGER,
    KASSA_AUTOGEN CHAR(1)

) RETURNS (

    CLIENT_ID INTEGER,
    SUM_DOLGA_Z NUMERIC(17,2),
    OPSUMM NUMERIC(17,2)

) AS

    DECLARE VARIABLE FIO VARCHAR(30);

BEGIN
    FOR SELECT CLIENT_ID, FIO FROM CLIENT INTO :CLIENT_ID, :FIO
    DO BEGIN
        SUM_DOLGA_Z = NULL;

        SELECT SUM(ZAKAZ.UNRDOLG * ZAKAZ.CUR_CURS)
        FROM ZAKAZ WHERE ZAKAZ.CLIENT_ID = :CLIENT_ID
        INTO :SUM_DOLGA_Z;

        IF (SUM_DOLGA_Z IS NULL) THEN SUM_DOLGA_Z = 0;

        OPSUMM = NULL;

        SELECT SUM(KASSA.OPSUMM * KASSA.OPCURCURS)
        FROM KASSA WHERE KASSA.OPKONTRA = :FIO AND OPSTAT = :OPSTAT AND KASSA_AUTOGEN = :KASSA_AUTOGEN
        INTO :OPSUMM;

        IF (OPSUMM IS NULL) THEN OPSUMM = 0;

        IF (OPSUMM - SUM_DOLGA_Z = 0) THEN SUSPEND;
    END;
END
5. Выполнить запрос
PHP:
SELECT C.FIO, G.SUM_DOLGA_Z, G.OPSUMM
FROM CLIENT C, GET_CLIENTS(31, 'T') G
WHERE C.CLIENT_ID = G.CLIENT_ID
 
Сверху