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ませtesttest_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_avtestFROM test_av

于 2012-10-09T20:49:48.953 に答える
1

あるサブクエリのエイリアスに別のサブクエリにアクセスする方法を尋ねました...一目でこれは、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

サブクエリの別の方法は、緯度と経度の 2 つの列に対して 2 つの選択を追加し、外部クエリをエイリアスで参照するだけです。これではパフォーマンスが低下するように見えますが、Oracle はこのタイプのクエリで素晴らしい仕事をします。単一の列選択ではグループは必要ありません。必要でない限り、null ではなく空の文字列を返すことを考えます。オラクルが「else」の状況で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

最後のコメントを追加します。2 番目のクエリは、計算で経度と緯度の値が使用されるため、OP が望んでいたものを取得しません。これはネストされたクエリの一例ですが、OP の質問に対する解決策ではありません。誤解を招いたら申し訳ありません。

于 2012-10-09T20:58:39.337 に答える
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 

SQL Server CROSS APPLY クエリを Oracle で動作させるために、過去のプロジェクトで私に与えられた黒魔術以外は何も知らないので、その CAST(MULTISET(..)) 全体を確認する必要があります。 .

于 2012-10-09T20:55:03.270 に答える