Sql 甲骨文';无效标识符';在子查询中
当子查询引用外部查询中的列时,我在将视图从PostgreSQL转换为Oracle时遇到问题 这个问题似乎已经在这里讨论过好几次了,但是我无法得到任何修复来处理我的特定查询 查询的目的是获取移动设备上一次记录的位置,并获取距离最近的检查点/地理边界的距离(以KM为单位),它引用3个单独的表:设备、设备位置和检查点Sql 甲骨文';无效标识符';在子查询中,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,当子查询引用外部查询中的列时,我在将视图从PostgreSQL转换为Oracle时遇到问题 这个问题似乎已经在这里讨论过好几次了,但是我无法得到任何修复来处理我的特定查询 查询的目的是获取移动设备上一次记录的位置,并获取距离最近的检查点/地理边界的距离(以KM为单位),它引用3个单独的表:设备、设备位置和检查点 SELECT d.id, dl.latitude AS last_latitude, dl.longitude AS last_longitude, (
SELECT
d.id,
dl.latitude AS last_latitude,
dl.longitude AS last_longitude,
(SELECT * /* Get closest 'checkpoint' to the last device position by calculating the Great-circle distance */
FROM (
SELECT
6371 * acos(cos(dl.latitude / (180/acos(-1))) * cos(checkpoints.latitude / (180/acos(-1))) * cos((checkpoints.longitude / (180/acos(-1))) - (dl.longitude / (180/acos(-1)))) + sin(dl.latitude / (180/acos(-1))) * sin(checkpoints.latitude / (180/acos(-1)))) AS distance
FROM checkpoints
ORDER BY distance)
WHERE ROWNUM = 1) AS distance_to_checkpoint
FROM devices d
LEFT JOIN ( /* Get the last position of the device */
SELECT l.id,
l.time,
l.latitude,
l.longitude,
l.accuracy
FROM device_locations l
WHERE l.ROWID IN (SELECT MAX(ROWID) FROM device_locations GROUP BY id)
ORDER BY l.id, l.time DESC) dl
ON dl.id = d.id;
我在这方面已经坚持了一段时间,希望有人能把我带上正确的道路,谢谢。我看到两个问题:
作为到检查点的距离,
device\u locations l
,而不是派生表dl
-示例:l.latitude
应为dl.latitude
作为到检查点的距离,
device\u locations l
,而不是派生表dl
-示例:l.latitude
应为dl.latitude
首先:查询不会获取最后一个设备位置。它根据
ID
获取具有最高ROWID
的记录,该记录可能恰好是最新条目,但根本不能保证是最新条目
那么,您很可能对范围有问题。不幸的是,名称仅在一个级别深度有效,这是一个令人恼火的限制dl.latitude
等在子查询中可能无效,因为它实际上是子查询中的子查询。不管怎样,您想要得到的是最小距离,您可以使用MIN
轻松获得该距离
在标准SQL中,子查询中的ORDER BY
是多余的。Oracle为他们的ROWNUM
技术提供了一个例外,但我不会使用这个。(如前所述,获取最小值甚至很笨拙。)外部联接中的ORDER BY
无论如何都是多余的
这就是我处理问题的方法:
select
d.id as device_id,
dl.latitude as last_latitude,
dl.longitude as last_longitude,
(
select min(6371 *
acos(cos(dl.latitude / (180/acos(-1))) *
cos(cp.latitude / (180/acos(-1))) *
cos((cp.longitude / (180/acos(-1))) - (dl.longitude / (180/acos(-1))))
+
sin(dl.latitude / (180/acos(-1))) *
sin(cp.latitude / (180/acos(-1)))
)
)
from checkpoints cp
) as distance
from devices d
left join
(
select
id as device_id, latitude, longitude, time,
max(time) over (partition by id) as max_time
from device_locations
) dl on dl.device_id = d.id and dl.time = dl.max_time;
首先:查询不会获取最后一个设备位置。它根据
ID
获取具有最高ROWID
的记录,该记录可能恰好是最新条目,但根本不能保证是最新条目
那么,您很可能对范围有问题。不幸的是,名称仅在一个级别深度有效,这是一个令人恼火的限制dl.latitude
等在子查询中可能无效,因为它实际上是子查询中的子查询。不管怎样,您想要得到的是最小距离,您可以使用MIN
轻松获得该距离
在标准SQL中,子查询中的ORDER BY
是多余的。Oracle为他们的ROWNUM
技术提供了一个例外,但我不会使用这个。(如前所述,获取最小值甚至很笨拙。)外部联接中的ORDER BY
无论如何都是多余的
这就是我处理问题的方法:
select
d.id as device_id,
dl.latitude as last_latitude,
dl.longitude as last_longitude,
(
select min(6371 *
acos(cos(dl.latitude / (180/acos(-1))) *
cos(cp.latitude / (180/acos(-1))) *
cos((cp.longitude / (180/acos(-1))) - (dl.longitude / (180/acos(-1))))
+
sin(dl.latitude / (180/acos(-1))) *
sin(cp.latitude / (180/acos(-1)))
)
)
from checkpoints cp
) as distance
from devices d
left join
(
select
id as device_id, latitude, longitude, time,
max(time) over (partition by id) as max_time
from device_locations
) dl on dl.device_id = d.id and dl.time = dl.max_time;
这是我另一个答案的后续。为了获得距离最小的
检查点
记录,您需要加入表并再次使用窗口函数来选择最佳记录。例如:
select
device_id,
last_latitude,
last_longitude,
checkpoint_latitude,
checkpoint_longitude,
distance
from
(
select
device_id,
last_latitude,
last_longitude,
checkpoint_latitude,
checkpoint_longitude,
distance,
min(distance) over (partition by device_id) as min_distance
from
(
select
d.id as device_id,
dl.latitude as last_latitude,
dl.longitude as last_longitude,
cp.latitude as checkpoint_latitude,
cp.longitude as checkpoint_longitude,
6371 *
acos(cos(dl.latitude / (180/acos(-1))) *
cos(cp.latitude / (180/acos(-1))) *
cos((cp.longitude / (180/acos(-1))) - (dl.longitude / (180/acos(-1))))
+
sin(dl.latitude / (180/acos(-1))) *
sin(cp.latitude / (180/acos(-1)))
) as distance
from devices d
left join
(
select
id as device_id, latitude, longitude, time,
max(time) over (partition by id) as max_time
from device_locations
) dl on dl.device_id = d.id and dl.time = dl.max_time
cross join checkpoints cp
)
)
where (distance = min_distance) or (distance is null and min_distance is null);
从Oracle 12c开始,使用
交叉应用
和外部应用
编写此类查询更容易。这是我的另一个答案的后续内容。为了获得距离最小的检查点
记录,您需要加入表并再次使用窗口函数来选择最佳记录。例如:
select
device_id,
last_latitude,
last_longitude,
checkpoint_latitude,
checkpoint_longitude,
distance
from
(
select
device_id,
last_latitude,
last_longitude,
checkpoint_latitude,
checkpoint_longitude,
distance,
min(distance) over (partition by device_id) as min_distance
from
(
select
d.id as device_id,
dl.latitude as last_latitude,
dl.longitude as last_longitude,
cp.latitude as checkpoint_latitude,
cp.longitude as checkpoint_longitude,
6371 *
acos(cos(dl.latitude / (180/acos(-1))) *
cos(cp.latitude / (180/acos(-1))) *
cos((cp.longitude / (180/acos(-1))) - (dl.longitude / (180/acos(-1))))
+
sin(dl.latitude / (180/acos(-1))) *
sin(cp.latitude / (180/acos(-1)))
) as distance
from devices d
left join
(
select
id as device_id, latitude, longitude, time,
max(time) over (partition by id) as max_time
from device_locations
) dl on dl.device_id = d.id and dl.time = dl.max_time
cross join checkpoints cp
)
)
where (distance = min_distance) or (distance is null and min_distance is null);
从Oracle 12c开始,使用
交叉应用
和外部应用
,这样的查询更容易编写。这里有一个额外的逗号作为距离检查点,
查询不获取最后的设备位置。它根据ID
获取具有最高ROWID
的记录,该记录可能恰好是最新条目,但根本不能保证是最新条目。您如何确定最后一个位置?通过时间
列?不管名称如何,device\u locations
中的ID
不是表的ID?而是设备ID?你应该彻底改变这个名字。顺便说一句,子查询中的ORDER BY
子句是完全多余的。您使用的是哪种Oracle版本?您想查看所有设备ID,即使是没有设备位置记录的设备ID也不例外?这里有一个额外的逗号作为距离检查点,
查询不会获取最后的设备位置。它根据ID
获取具有最高ROWID
的记录,该记录可能恰好是最新条目,但根本不能保证是最新条目。您如何确定最后一个位置?通过时间
列?不管名称如何,device\u locations
中的ID
不是表的ID?而是设备ID?你应该彻底改变这个名字。顺便说一句,子查询中的ORDER BY
子句是完全多余的。您使用的是哪个Oracle版本?您想查看所有设备ID,即使是那些没有设备位置记录的设备ID?谢谢,我已经解决了这些问题,但在大圆距离子查询中仍然有一个无效标识符:ORA-00904:“DL”“LATITUDE”:无效标识符00904.00000-“%s:无效标识符”*原因:*操作:第8行错误列:192谢谢我已修复了这些问题,但在大圆距离子查询ORA-00904中仍然存在无效标识符:“DL”“LATITUDE”:无效标识符00904.00000-“%s:无效标识符”“*原因:*操作:第8行错误列:192这似乎解决了我的问题,非常感谢您的帮助。我确实有一个疑问