如何构造此Oracle SQL查询?

时间:2012-10-09 20:24:01

标签: sql oracle

我在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'。我试图访问子查询别名,但查询失败。

如何将一个子查询的“别名”访问到另一个子查询?

3 个答案:

答案 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问题的解决方案。对不起,如果它误导了任何人。