2012-01-09 9 views
4

これは単純なように見えるかもしれませんが、何とかそうではありません。私が持っているこのようになりますTBL_Aと呼ばれる実績率データのテーブル:サブクエリの最初の行にOracleが結合します

| id | hours | added_date | 
|--------|---------|--------------| 
| bill | 10 | 2/26/2011 | 
| ted | 4  | 7/4/2011 | 
| bill | 9  | 10/14/2011 | 

TBL_Bで
| id | rate | added_date | 
|--------|--------|--------------| 
| bill | 7.50 | 1/24/2011 | 
| joe | 8.50 | 5/3/2011 | 
| ted | 8.50 | 4/17/2011 | 
| bill | 9.00 | 9/29/2011 | 

、私は原価計算の情報を取得するために、TBL_Aの単一の行に参加する必要がある時間を持っています

ご覧のとおり、Billの場合、TBL_Aには2つの料金がありますが、日付は異なります。一定期間Billのコストを適切に取得するには、TBL_Aの行にTBL_Bの各行をその日付に合うように参加させる必要があります。

これは簡単だと思いました。これは例外的に高速なクエリを必要としないため、コスト情報の各行に対して個別のサブクエリを実行できます。ただし、結合されたサブクエリは、結合された他のテーブルを「見る」ことはできません。問題は、単にアプローチは、私が今までできを取った場合、私は知らない、スコーピングされている場合は

SELECT h.id, r.rate * h.hours as "COST", h.added_date 
    FROM TBL_B h 
    JOIN (SELECT * FROM (
       SELECT i.id, i.rate 
        FROM TBL_A i 
       WHERE i.id = h.id and i.added_date < h.added_date 
       ORDER BY i.added_date DESC) 
      WHERE rownum = 1) r 
     ON h.id = r.id 

:このクエリは、「H」の別名を持つサブクエリで何かに無効な識別子を(ORA-00904)スロー作業。しかし、私がここでやろうとしているのは、いくつかの基準に基づいて単一の行を得ることなので、私は他のメソッドには絶対にオープンです。

EDIT:ビルは、テーブル内の2つのエントリ内の2つの異なる速度を有する

| id | cost | added_date | 
|--------|---------|--------------| 
| bill | 75 | 2/26/2011 | 
| ted | 34 | 7/4/2011 | 
| bill | 81 | 10/14/2011 | 

注:所望の出力は、このあろう。最初の行は、10 * 7.50 = 75であり、2行目は、9×9.00 = 81

+0

希望する出力は何ですか?時間の合計? –

+0

私はそれがあいまいだったと思う、私はより具体的に私の質問を編集しました。 – monitorjbl

答えて

4

not existsを使用してみます:

select 
    b.id, 
    a.rate, 
    b.hours, 
    a.rate*b.hours as "COST", 
    b.added_date, 
    a.added_date 
from 
    tbl_b b 
    inner join tbl_a a on 
     b.id = a.id 
where 
    a.added_date < b.added_date 
    and not exists (
     select 
      1 
     from 
      tbl_a a2 
     where 
      a2.added_date > a.added_date 
      and a2.added_date < b.added_date 
      and a2.id = a.id 
     ) 

これが起こっている理由を説明とおりのみ相関サブクエリが知っていますそれぞれの行で実行されているため、実行されているコンテキストです。ジョインされたサブクエリは実際にジョインに先立って実行されるため、周囲のテーブルについての知識はありません。サブクエリ内でそれを実行しようとするのではなく、問合せの最上位レベルで結合を行うために、すべての識別情報を戻す必要があります。

+0

説明をありがとう、非常に啓発され、私のコードがうまくいかない理由が完全に説明されています。しかし、このアプローチはどちらもうまくいかない。私のポストの例では、Billは "7.50"のレートで結合する必要がある行を持っています。投稿したコードでは、row_number()の値は2になるため、完全に除外されます。 "これがX個の行を返す場合"(これは私がSQL仕様に違反していることは間違いない)WHERE句に何らかの方法を含めない限り、サブクエリ自体に値を注入する方法が必要だと思います。 – monitorjbl

+0

@monitorjbl - Ah、gotcha。私はあなたのお手伝いをするべきである「存在しない」でこれを行いました。この述部は、表が計算された後に行われるため、それらの列を使用できます。それはまたかなり速いです。私は臨時のテーブルでこれを行い、期待された結果を返しました。 – Eric

+0

ああ!それは完璧に動作します、ありがとう。私は "存在"のキーワードについて知らなかった、毎日何か新しいことを学ぶ! – monitorjbl

1
select id, cost, added_date from (
select 
    h.id, 
    r.rate * h.hours as "COST", 
    h.added_date, 
    -- For each record, assign r=1 for 'newest' rate 
    row_number() over (partition by h.id, h.added_date order by r.added_date desc) r 
from 
    tbl_b h, 
    tbl_a r 
where 
    r.id = h.id and 
    -- Date of rate must be entered before 
    -- hours billed: 
    r.added_date < h.added_date 
) 
where r = 1 
; 
+0

あなたの答えをありがとう、Rene。残念ながら、これは動作しません。これはEricが彼の編集前に取ったのと同じアプローチであり、なぜ彼はそれがうまくいかない理由を説明する彼の投稿にコメントを残しました。 – monitorjbl

+0

私が見る限り、それはエリックが行っていたのと同じルートではなく、私はまだそれがあなたの意図することを信じています。エリックは彼の答えを編集する前に別の質問をしていました。 –

+0

Ericの最初のクエリは、あなたと非常によく似ていました。彼はちょうど異なる結合構文を使用しました。彼の元のクエリ(とあなた)の問題は、これは常にTBL_Bの**任意の**行をTBL_Aの**最新の**行に結合するということです。私が探していたのはTBL_Bの最新の_date-appropriate_行でした。 TBL_AとTBL_Bの両方に従業員のエントリが2つある場合、TBL_Bの各行をTBL_Aの異なる行に結合する必要があることが反映されている必要があります(結果は最新のものだけでなく、 ) – monitorjbl

関連する問題