@SLJ

Как посчитать сумму одинаковых значений по одной колонке, но разных по другой?

Имеется действующая БД под Firebird, база для продаж.
Имеется следующий запрос:
SELECT
        (C.CODE) AS "Табельный", (C.NAME) AS "Ф.И.О.",
        T.TRANZDATE AS "Дата", T.TRANZTIME AS "Время",
        (T.INFOSTR) AS "Карта", T.SUMM AS "Сумма"

FROM DOCUMENT D LEFT JOIN TRANZT T ON
                  D.ID = T.DOCUMENTID
                  JOIN CLIENT C ON
                  D.CLIENTID = C.ID

WHERE
      T.TRANZDATE >='20.02.2020' AND T.TRANZDATE <='20.02.2020' AND
      T.TRANZTIME >='18:55:00' AND T.TRANZTIME <='23:59:59' AND
      D.STATE = 1 AND
      (D.ISFISCAL = 1) AND
      D.CLIENTID >=0 AND
      T.TRANZTYPE = '36'

GROUP BY C.CODE, C.NAME, T.TRANZDATE, T.TRANZTIME, T.INFOSTR, T.SUMM
ORDER BY C.NAME ASC, T.TRANZDATE ASC, T.TRANZTIME ASC, T.SUMM DESC

В результате которого получаю следующее:
Таб-й      ФИО                           Дата        Время     Карта     Сумма

7 845  Иванов Иван Иванович              20.02.2020  20:17:41  1953722   12,000  
1 526  Паршуков Иоан Иванович         20.02.2020  20:17:13  1953793   20,000  
4 815  Колымин Константин Александрович  20.02.2020  20:16:54  13694802  20,000  
4 613  Сидоров Андрей Анатольевич        20.02.2020  20:18:08  1593579   12,000  
4 613  Сидоров Андрей Анатольевич        20.02.2020  20:18:38  1593579    6,000


Суть вопроса: что необходимо дописать чтобы Сидоров Андрей Анатольевич имел не две раздельные записи по 12 и 6 соответственно, а сразу показал сумму 18? т.е. необходимо из таблицы document в столбце clientid найти одинаковые значения (номера карт) и если таковы имеются, то сложить значения summ из таблицs tranzt.
Если понадобится таблицы, могу скинуть.
  • Вопрос задан
  • 1581 просмотр
Решения вопроса 1
trapwalker
@trapwalker
Программист, энтузиаст
Уберите T.TRANZTIME из группировки и из селекта. Там два разных значения.
Если вам обязательно надо какое-то показать (например последнее), то выкиньте его из группировки, а в селекте поставьте там агрегатор, например, max.
Вот так ваш Сидоров просуммируется на этом датасете в одну строку:
SELECT
    C.CODE AS "Табельный",
    C.NAME AS "Ф.И.О.",
    T.TRANZDATE AS "Дата",
    max(T.TRANZTIME) AS "Время",
    T.INFOSTR AS "Карта",
    sum(T.SUMM) AS "Сумма"
FROM 
    DOCUMENT D
        LEFT JOIN TRANZT T ON D.ID = T.DOCUMENTID
        JOIN CLIENT C ON D.CLIENTID = C.ID
WHERE
      T.TRANZDATE >='20.02.2020' AND T.TRANZDATE <='20.02.2020' AND
      T.TRANZTIME >='18:55:00' AND T.TRANZTIME <='23:59:59' AND
      D.STATE = 1 AND
      D.ISFISCAL = 1 AND
      D.CLIENTID >=0 AND
      T.TRANZTYPE = '36'
GROUP BY
    C.CODE,
    C.NAME,
    T.TRANZDATE,
--    T.TRANZTIME,
    T.INFOSTR
--    ,T.SUMM

Но на этом ваши проблемы не кончатся. В вашем SQL много других косяков:
  1. Какой смысл делать такое условие: T.TRANZTIME <='23:59:59'? Любое время будет ему удовлетворять.
  2. Если ваши дата и время связаны, то есть определяют какой-то момент во времени, то их нужно хранить и фильтровать как единое значение, иначе вы сами не заметите как наткнётесь на не очевидную (для новичка) ошибку неконсистентности. К примеру, событие Б позднее события А, но А произошло вечером, а Б утром (другого дня). При вашем отдельном сравнении дат и времён может получиться некорректность из-за того, что время (без даты) события А > времени (без даты) события Б. Соедините дату и время в единое поле datetime или соединяйте их каждый раз когда делаете условную фильтрацию по временнОму диапазону.
  3. Зачем вы группируете по T.SUMM, если собирались агрегировать это поле?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы