我在Oracle中编写一个sql查询,如下所示:
SELECT *
FROM ( SELECT testid,
max(decode(name, 'longitude', stringvalue, NULL)) as longitude,
max(decode(name, 'latitude', stringvalue, NULL)) as latitude
FROM test_av
GROUP BY testid
) av
INNER JOIN (
SELECT id,
((ACOS(
SIN(16.15074 * 3.141592653 / 180)
* SIN(latitude * 3.141592653 / 180)
+ COS(16.15074 * 3.141592653 / 180)
* COS(latitude * 3.141592653 / 180)
* COS((-22.74426 - longitude)*3.141592653 / 180)
)*6373)) as distance
FROM test
) t ON t.id = av.testid
WHERE t.distance <= 100
当我执行此查询时,Oracle会说'longitude invalid identifier'
。我试图访问子查询别名,但查询失败。
如何将一个子查询的“别名”访问到另一个子查询?
答案 0 :(得分:2)
如果我正确理解您要做的事情,那么您实际上并不需要INNER JOIN
,因为您没有从test
那里获取任何尚未提供的实际信息{ {1}}。所以,你可以写:
test_av
如果您想明确确保只获取SELECT *
FROM ( SELECT id,
longitude,
latitude,
((ACOS( SIN(16.15074 * 3.141592653 / 180)
* SIN(latitude * 3.141592653 / 180)
+ COS(16.15074 * 3.141592653 / 180)
* COS(latitude * 3.141592653 / 180)
* COS((-22.74426 - longitude) * 3.141592653 / 180)
)*6373)) AS distance
FROM ( SELECT testid AS id,
max(decode(name, 'longitude', stringvalue, NULL)) as longitude,
max(decode(name, 'latitude', stringvalue, NULL)) as latitude
FROM test_av
GROUP
BY testid
)
)
WHERE distance <= 100
;
中存在的记录 - 也就是说,如果test
中的记录中没有父项test_av
,则你希望过滤掉那些 - 然后你可以在test
之后在最里面的子查询中处理它。
答案 1 :(得分:1)
好吧,我是一个SQL Server专家,而不是Oracle大师,但我认为你想要这样的东西:
SELECT *
FROM ( SELECT testid,
max(decode(name, 'longitude', stringvalue, NULL)) as longitude,
max(decode(name, 'latitude', stringvalue, NULL)) as latitude
FROM test_av av
GROUP BY testid
) av,
TABLE ( CAST (MULTISET(
SELECT id,
((ACOS(
SIN(16.15074 * 3.141592653 / 180)
* SIN(latitude * 3.141592653 / 180)
+ COS(16.15074 * 3.141592653 / 180)
* COS(latitude * 3.141592653 / 180)
* COS((-22.74426 - longitude)*3.141592653 / 180)
)*6373)) as distance
FROM test ti
WHERE ti.id = av.testid
)
)) t
WHERE t.distance <= 100
你需要检查整个CAST(MULTISET(..))的东西,因为我对它一无所知,除了它是在过去的项目中给我的一些黑魔法,以获得SQL Server CROSS APPLY查询在甲骨文工作。
答案 2 :(得分:1)
您询问如何将一个子查询的别名访问到另一个...快速浏览这是通过使用两个“模拟表”来实现它的一种方法。您可以使用像这样的表之类的select语句。不确定这是否是您最好的解决方案,但应该让您走上正确的轨道。
SELECT testav.*, testt.*
FROM
( SELECT av.testid as id,
max(decode(av.name, 'longitude', stringvalue, NULL)) as longitude,
max(decode(av.name, 'latitude', stringvalue, NULL)) as latitude
FROM test_av av
GROUP BY av.testid
) testav,
(SELECT t.id as id,
((ACOS(
SIN(16.15074 * 3.141592653 / 180)
* SIN(t.latitude * 3.141592653 / 180)
+ COS(16.15074 * 3.141592653 / 180)
* COS(t.latitude * 3.141592653 / 180)
* COS((-22.74426 - t.longitude)*3.141592653 / 180)
)*6373)) as distance
FROM test t
) testt
WHERE testav.id = testt.id
and testt.distance <= 100
子查询的另一种方法是为纬度和经度的两列添加两个选择,并通过别名引用外部查询。这似乎是性能不佳,但Oracle在这种类型的查询方面做得很好。单列选择不需要组。除非你需要,否则我会考虑返回空字符串而不是null。我不确定Oracle是否会因“其他”情况而感谢null。我想这一定是为你工作的。
SELECT id,
ACOS(..snipped details..)*6373) as distance,
(SELECT max(decode(av.name, 'longitude', stringvalue, NULL))
FROM test_av
WHERE test_av.testid = av.id) as longitude,
(SELECT max(decode(av.name, 'latitude', stringvalue, NULL))
FROM test_av
WHERE test_av.testid = av.id) as latitude
FROM test_av av
WHERE av.distance <= 100
添加最终评论。第二个查询不会得到OP想要的,因为在计算中使用了经度和纬度值。这是嵌套查询的一个示例,但不是OP问题的解决方案。对不起,如果它误导了任何人。