给定这样的表格,每个监视器的最新校准信息是什么?换句话说,我想找到每个监视器的最大日期值。特定于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
答案 0 :(得分:19)
我倾向于使用分析函数
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)
答案 1 :(得分:11)
我个人的偏好是:
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
的{{1}}语法。无论哪种方式都有效。
答案 2 :(得分:2)
窗口函数解决方案应该最有效,并且只能进行一次表或索引扫描。我在这里发帖的那个我认为通过直观和易于理解赢得了一些观点。我在SQL服务器上进行了测试,它在窗口函数中执行了第二次,导致了两次索引扫描。
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 server中)。这个在执行计划中使用Left Outer Join,其中第一个使用Anti-Semi Merge Join:
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
答案 3 :(得分:1)
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
)