Проблема с агрегатом

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
Лысый
Сообщения: 177
Зарегистрирован: 08 ноя 2004, 08:20

Проблема с агрегатом

Сообщение Лысый » 27 сен 2006, 11:16

FB 1.5.3

Есть запрос:

Код: Выделить всё

SELECT CASE WHEN P.CODE_TYPE = 1 THEN '1. Зубопротезирование'
            WHEN P.CODE_TYPE = 2 THEN '2. Слухопротезирование'
            ELSE '3. Не определено' END AS CODE_TYPE
     , O.NAME AS REGION
     , H.ID_HOSPITAL
     , MAX(H.SHORT_NAME) AS HOSPITAL
     , SUM(CASE WHEN RE.ID_PARENT IS NOT NULL AND RD.ID_DEFECT IS NULL
                THEN 0 ELSE RE.STO END) AS SUM_TOTAL
     , (SUM(CASE WHEN RE.IS_DEFECT_T = 1 THEN RE.STO ELSE 0 END) -

       SUM(CASE WHEN RE.ID_PARENT IS NOT NULL AND RD.ID_DEFECT IS NULL
                THEN RE.STO ELSE 0 END)) AS SUM_DEFECT_T

     , SUM(CASE WHEN RE.IS_DEFECT_M = 1 THEN RE.SUM_DEFECT_M ELSE 0 END) AS SUM_DEFECT_M
     , SUM(CASE WHEN RDM.SUM_DEFECT IS NULL THEN 0 ELSE RDM.SUM_DEFECT END) AS SUM_DEFECT_M2
     , SUM(RE.SUM_PAY - CASE WHEN RDM.SUM_DEFECT IS NULL THEN 0 ELSE RDM.SUM_DEFECT END)  AS SUM_PAY
     , (SELECT SUM(PM.SUM_PAY)
          FROM PAYMENT PM JOIN HOSPITAL_CONTRACT HC ON (PM.ID_HOSPITAL_CONTRACT = HC.ID_HOSPITAL_CONTRACT)
         WHERE PM.ID_HOSPITAL = H.ID_HOSPITAL
           AND PM.D_DOCUMENT <= :D_END
           AND HC.CODE_TYPE = P.CODE_TYPE) AS SUM_PAYMENT
  FROM HOSPITAL H
       JOIN ROLL R ON (H.ID_HOSPITAL = R.ID_HOSPITAL)
       JOIN ROLL_EVENT RE ON (R.ID_ROLL = RE.ID_ROLL)
       LEFT JOIN PGG P ON RE.KOD_PGG = P.CODE_PGG
       JOIN OKATO O ON (H.ID_OKATO = O.ID_OKATO)
       LEFT JOIN ROLL_DEFECT RD ON (RE.ID_ROLL_EVENT = RD.ID_ROLL_EVENT) AND (RD.ID_DEFECT = 60)
       LEFT JOIN ROLL_DEFECT_M RDM ON (RE.ID_ROLL_EVENT = RDM.ID_ROLL_EVENT) AND (RDM.D_SAVE <= :D_END)
 WHERE R.D_SAVE <= :D_END
   AND R.CODE_STATUS <> 0
 GROUP BY 1, 2, 3
в таком виде он не компилится с ошибкой:
SQL error code = -104.
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause).


Если в секции:

Код: Выделить всё

(SELECT SUM(PM.SUM_PAY)
          FROM PAYMENT PM JOIN HOSPITAL_CONTRACT HC ON (PM.ID_HOSPITAL_CONTRACT = HC.ID_HOSPITAL_CONTRACT)
         WHERE PM.ID_HOSPITAL = H.ID_HOSPITAL
           AND PM.D_DOCUMENT <= :D_END
           AND HC.CODE_TYPE = P.CODE_TYPE) AS SUM_PAYMENT
убрать AND HC.CODE_TYPE = P.CODE_TYPE, то запрос компилится, но результат не верен - оплата идет не в разрезе типа договора, а в разрезе ЛПУ... происходит задвоение оплаты.
Что то я сообразить не могу как это обойти...
Можно конечно через хроник переписать запрос, но не очень хочется это делать...

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 27 сен 2006, 11:51

А если написать не "(SELECT SUM(PM.SUM_PAY) FROM PAYMENT ...", а "SUM((SELECT SUM(PM.SUM_PAY) FROM PAYMENT ...", компилится?

Лысый
Сообщения: 177
Зарегистрирован: 08 ноя 2004, 08:20

Сообщение Лысый » 27 сен 2006, 12:12

WildSery писал(а):А если написать не "(SELECT SUM(PM.SUM_PAY) FROM PAYMENT ...", а "SUM((SELECT SUM(PM.SUM_PAY) FROM PAYMENT ...", компилится?
Попробовал - нет.
Я так понимаю, что вся проблема в то что я пытаюсь для корелляции использовать P.CODE_TYPE, но тогда почему получилось внести H.ID_HOSPITAL, чем они отличаются?

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 27 сен 2006, 12:44

По H.ID_HOSPITAL группирвка есть, а по P.CODE_TYPE - нет. И это большая разница. Сервер не знает какой именно P.CODE_TYPE использовать.

Лысый
Сообщения: 177
Зарегистрирован: 08 ноя 2004, 08:20

Сообщение Лысый » 27 сен 2006, 12:51

Dimitry Sibiryakov писал(а):По H.ID_HOSPITAL группирвка есть, а по P.CODE_TYPE - нет. И это большая разница. Сервер не знает какой именно P.CODE_TYPE использовать.
Совершенно точно! Уже сделал :) Всем спасибо.

Ответить