Min и Max в одном запросе?

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

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

Ответить
vserd
Сообщения: 10
Зарегистрирован: 31 авг 2006, 17:15

Min и Max в одном запросе?

Сообщение vserd » 25 сен 2006, 12:28

Всем Доброго здравия!!!

Помогите объединить два запроса в один.
Есть табличка с показаниями счетчиков.
ID_OBJ Integer
Dt Timestamp
Cnt1 double
cnt2 double

мне нужно вывести в одной строке показания на начало и конец периода.

Сами запросы я написал
Для начала периода:

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

select * from counter_view cv
where cv.dt = (select mIn(cv1.dt) from counter_view  cv1 where (cv1.dt >= :begin_DaTE) and (cv1.dt < :EndDate)
and cv1.id_Obj = cv.id_obj)
Для конца периода:

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

select * from counter_view cv
where cv.dt = (select max(cv1.dt) from counter_view  cv1 where (cv1.dt >= :begin_DaTE) and (cv1.dt < EndDate)
and cv1.id_Obj = cv.id_obj)
а как объединить их в один запрос со структурой
ID_OBJ
Date_Begin
Date_End
Cnt1_Begin
Cnt1_End
Cnt2_Begin
Cnt2_End

туплю......
Подскажите пожауйста.

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

Сообщение Dimitry Sibiryakov » 25 сен 2006, 12:36

Лично я бы написал ХП для этого...

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

Сообщение WildSery » 25 сен 2006, 14:21

union all

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 25 сен 2006, 16:22

UNION ALL тут не поможет...
1. Почему описание counter_view приведено не полностью (не вижу поля первичного ключа)?
2. Показания для каждого объекта вводятся каждый день?
3. Почему проверка начала через " >= :DateBegin", а конца через " < :DateEnd"?
4. Запросы точно рабочие? Или теоретически должны работать? Если это точно рабочие, ты их по памяти писал или как?

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

Сообщение WildSery » 25 сен 2006, 18:43

CyberMax писал(а):UNION ALL тут не поможет...
Я не ставил целью объяснять автору, почему у него запросы неправильные, а показал, что он с ними может сделать. Результат не ухудшится :wink:
CyberMax писал(а):1. Почему описание counter_view приведено не полностью (не вижу поля первичного ключа)?
Автор писал ID_OBJ Integer, вероятно, это и есть PK
CyberMax писал(а):Почему проверка начала через " >= :DateBegin", а конца через " < :DateEnd"?
Я думаю, для того, чтобы день вычленять полностью, '25.09.2006 00:00:00' <= Дата < '26.09.2006 00:00:00', а не записывать кривду типа '23:59:59.999' которая ещё не везде и работать будет.

vserd
Сообщения: 10
Зарегистрирован: 31 авг 2006, 17:15

Сообщение vserd » 25 сен 2006, 19:15

CyberMax
1. Почему описание counter_view приведено не полностью (не вижу поля первичного ключа)?
Первичный ID_OBJ, ID - где ID это номер записи в таблице
2. Показания для каждого объекта вводятся каждый день?
Как минимум раз в сутки, как максимум.... Как позволит быстродейстиве каналов...
3. Почему проверка начала через " >= :DateBegin", а конца через " < :DateEnd"?
WildSery Ответил, только не 00:00:00 а 8:00:00 но в данном контесте не важно.
4. Запросы точно рабочие? Или теоретически должны работать? Если это точно рабочие, ты их по памяти писал или как?
Запросы точно рабочие, из проекта.

2 WildSery
Я не ставил целью объяснять автору, почему у него запросы неправильные, а показал, что он с ними может сделать. Результат не ухудшится
И чем мне поможет результат
  • ID_OBJ Date_Begin Date_End Cnt1_Begin Cnt1_End Cnt2_Begin Cnt2_End
    1, 01.09.06 9:44, NULL, 1234, NULL, 5678, NULL
    1, NULL, 01.09.06 23:13, NUll , 3456, null, 4567,
?

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

Сообщение WildSery » 25 сен 2006, 20:22

vserd писал(а):И чем мне поможет результат?
Сгруппировать надо потому шта. Но не на всяком сервере.
Делай ХП, не парь себя и сервер.

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

begin
  select first 1 ID_OBJ, Dt, Cnt1, cnt2
    from counter_view
    where dt >= :begin_DaTE and dt < :EndDate
    order by dt
    into ID_OBJ, Date_Begin, Cnt1_Begin, Cnt1_End;

  select first 1 Dt, Cnt1, cnt2
    from counter_view
    where dt >= :begin_DaTE and dt < :EndDate
    order by dt desc
    into Date_End, Cnt2_Begin, Cnt2_End;

  suspend;
end;
Для скорости нужны нисходящий и восходящий индекс по dt.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 26 сен 2006, 04:35

vserd писал(а):Первичный ID_OBJ, ID - где ID это номер записи в таблице
ПК по полям ID_OBJ и ID, я правильно понял? А ID случайно не через генератор получаешь?

Andrew Sagulin
Сообщения: 53
Зарегистрирован: 11 мар 2005, 15:44

Сообщение Andrew Sagulin » 26 сен 2006, 09:22

Кстати, безотносительно к решению исходного вопроса, если модифицировать запрос так:

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

select * from counter_view cv 
where cv.dt = (select min(cv1.dt) from counter_view  cv1 where (cv1.dt >= :begin_DaTE) and (cv1.dt < :EndDate)
and cv1.id_Obj = cv.id_obj)
and (cv.dt >= :begin_DaTE) and (cv.dt < :EndDate)
не быстрее работать будет?

vserd
Сообщения: 10
Зарегистрирован: 31 авг 2006, 17:15

Сообщение vserd » 26 сен 2006, 15:09

CyberMax писал(а):
vserd писал(а):Первичный ID_OBJ, ID - где ID это номер записи в таблице
ПК по полям ID_OBJ и ID, я правильно понял? А ID случайно не через генератор получаешь?
Да через генератор, но к выборке это не относится...

Вобщем, сделал я через Ж... работает, результат выдавало правильный, но все равно пришлось делать через ХП. Там подводный камень обнаружился, заказчик не доконца проработал исходные требования....

Результат

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

Select distinct rn.name, cv.id_obj,
   (Select cv2.cnt1 from counter_view cv2
     where cv2.dt = (select mIn(cv1.dt) from counter_view  cv1
                    where (cv1.dt >= :BeginDate) and (cv1.dt < :EndDate)
                    and cv1.id_Obj = cv.id_obj)) as Cnt1_Begin,
   (Select cv2.cnt1 from counter_view cv2
    where cv2.dt = (select max(cv1.dt) from counter_view  cv1
                    where (cv1.dt >= :BeginDate) and (cv1.dt < :EndDate) and
                           cv1.id_Obj = cv.id_obj)) as Cnt1_End,

   (Select cv2.cnt2 from counter_view cv2
    where cv2.dt = (select mIn(cv1.dt) from counter_view  cv1
                    where (cv1.dt >= :BeginDate) and (cv1.dt < :EndDate)
                    and cv1.id_Obj = cv.id_obj)) as Cnt2_Begin,
   (Select cv2.cnt2 from counter_view cv2
    where cv2.dt = (select max(cv1.dt) from counter_view  cv1
                    where (cv1.dt >= :BeginDate) and (cv1.dt < :EndDate)
                    and cv1.id_Obj = cv.id_obj)) as Cnt2_End

  From counter_view cv left join names rn on (cv.id_obj = rn.ID)
where  (cv.dt >= :BeginDate) and  (cv.dt < :EndDate)
Спасибо всем за помощь!!!

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

Сообщение Dimitry Sibiryakov » 26 сен 2006, 15:36

А если делаешь через ХП, зачем такие ужасы в запросе?

vserd
Сообщения: 10
Зарегистрирован: 31 авг 2006, 17:15

Сообщение vserd » 26 сен 2006, 18:20

Dimitry Sibiryakov писал(а):А если делаешь через ХП, зачем такие ужасы в запросе?
В ХП таких ужасов конечно же нет. Это мой вариант решения поставленного вопроса. Так сказать результат работы.
То что по ходу жизни изменились условия задачи, не отменяет опубликования результатов. Может кому пригодиться в другой ситуации.

Ответить