4

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

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

4

3 回答 3

2

如果我正确理解您正在尝试做的事情,那么您实际上并不需要INNER JOIN,因为您没有从中获取任何真实test信息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,并且你想过滤掉它们——那么你可以在最里面的子查询中处理它,之后你的FROM test_av.

于 2012-10-09T20:49:48.953 回答
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 查询在 Oracle 上工作.

于 2012-10-09T20:55:03.270 回答
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 问题的解决方案。对不起,如果它误导了任何人。

于 2012-10-09T20:58:39.337 回答