Oracle: получить максимальную стоимость группы? - PullRequest
9 голосов
/ 10 февраля 2012

Учитывая таблицу, подобную этой, какой запрос будет содержать самую последнюю информацию о калибровке для каждого монитора? Другими словами, я хочу найти максимальное значение даты для каждого из мониторов. Специфичная для Oracle функциональность подходит для моего приложения.

monitor_id     calibration_date  value
----------     ----------------  -----
1              2011/10/22        15
1              2012/01/01        16
1              2012/01/20        17
2              2011/10/22        18
2              2012/01/02        19

Результаты для этого примера будут выглядеть так:

1  2012/01/20 17
2  2012/01/02 19

Ответы [ 4 ]

19 голосов
/ 10 февраля 2012

Я бы предпочел использовать аналитические функции

SELECT monitor_id,
       host_name,
       calibration_date,
       value
  FROM (SELECT b.monitor_id,
               b.host_name,
               a.calibration_date,
               a.value,
               rank() over (partition by b.monitor_id order by a.calibration_date desc) rnk
          FROM table_name a,
               table_name2 b
         WHERE a.some_key = b.some_key)
 WHERE rnk = 1

Вы также можете использовать коррелированные подзапросы, хотя это будет менее эффективно

SELECT monitor_id,
       calibration_date,
       value
  FROM table_name a
 WHERE a.calibration_date = (SELECT MAX(b.calibration_date)
                               FROM table_name b
                              WHERE a.monitor_id = b.monitor_id)
11 голосов
/ 10 февраля 2012

Мои личные предпочтения таковы:

SELECT DISTINCT
       monitor_id
      ,MAX(calibration_date)
       OVER (PARTITION BY monitor_id)
       AS latest_calibration_date
      ,FIRST_VALUE(value)
       OVER (PARTITION BY monitor_id
             ORDER BY calibration_date DESC)
       AS latest_value
FROM mytable;

Вариантом будет использование синтаксиса FIRST_VALUE для latest_calibration_date.В любом случае работает.

2 голосов
/ 10 февраля 2012

Решение для оконных функций должно быть наиболее эффективным и привести к сканированию только одной таблицы или индекса.Я думаю, что тот, который я публикую здесь, выигрывает за интуитивность и простоту понимания.Я проверил на сервере SQL, и он выполнил функции 2-го к окну, что привело к двум просмотрам индекса.

SELECT T1.monitor_id, T1.calibration_date, T1.value
FROM someTable AS T1
WHERE NOT EXISTS 
(
    SELECT * 
    FROM someTable AS T2
    WHERE T2.monitor_id = T1.monitor_id AND T2.value > T1.value
)
 GROUP BY T1.monitor_id, T1.calibration_date, T1.value

И, черт возьми, вот еще один аналогичный пример, но менее производительный (63%Стоимость против 37%), чем другие (опять же на сервере SQL).В этом плане используется левое внешнее объединение в плане выполнения, в котором в качестве первого используется соединение с анти-полуслияниями:

SELECT T1.monitor_id, T1.calibration_date, T1.value
FROM someTable AS T1
LEFT JOIN someTable AS T2 ON T2.monitor_id = T1.monitor_id AND T2.value > T1.value
WHERE T2.monitor_id IS NULL
GROUP BY T1.monitor_id, T1.calibration_date, T1.value
1 голос
/ 10 февраля 2012
select monitor_id, calibration_date, value 
from table
where calibration_date in(
  select max(calibration_date) as calibration_date 
  from table
  group by monitor_id
  )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...