2016-04-19 14 views
0

郵便番号44444の郵便番号と郵便番号を別々に計算する必要があります。郵便番号は同じテーブルに格納されていますが、そのIDは多対多の2つの別々のテーブルにあります関係。私はこれを知っている2つの異なるselect文に影響を与えるwhere節

select count(mortal_zip) as "Mortals in 44444" 
     ,count(payer_zip) as "Payers in 44444" 
    from 
     (select am.zip_code as mortal_zip 
     from address am 
     join mortal_address 
      on mortal_address.address_id = am.address_id 
     join mortal 
      on mortal.mortal_id = mortal_address.mortal_id 
     where trim(am.zip_code) = '44444' 
     ) m, 
     (select ap.zip_code as payer_zip 
     from address ap 
     join payer_address 
      on payer_address.address_id = ap.address_id 
     join payer 
      on payer.payer_id = payer_address.payer_id 
     where trim(ap.zip_code) = '44444' 
     ) p; 

:私はこれを書かれている何の納税者は、44444の郵便番号ではありませんが、私は取得しています何らかの理由44444.の郵便番号を持つ3人の人間は0人間があることがあります44444の郵便番号。私が44444でただの人を求めるなら、私は必要なものを手に入れます。私が死人の数と支払人の数を444444で求めたら、私は両側で0を得ます。

さらに、私はサブセレクトですべてを書き直そうとしました。

select count(m.mortal_zip) as "Mortals in 44444" 
     ,count(p.payer_zip) as "Payers in 44444" 
    from 
     (select am.zip_code as mortal_zip 
     from address am 
     where trim(am.zip_code) = '44444' 
      and am.address_id in 
      (select mortal_address.address_id 
       from mortal_address 
       where mortal_address.mortal_id in 
        (select mortal.mortal_id 
        from mortal 
        ) 
      ) 
     ) m, 
     (select ap.zip_code as payer_zip 
     from address ap 
     where trim(ap.zip_code) = '44444' 
      and ap.address_id in 
      (select payer_address.address_id 
       from payer_address 
       where payer_address.payer_id in 
        (select payer.payer_id 
         from payer 
        ) 
      ) 
     ) p; 

私は同じ結果を得ます。

なぜ異なるselectステートメントのwhere関数が他のselectステートメントに影響しますか?

更新

私は、クエリを書き換えてきたが、これらの2つのクエリは、異なる値を返すされています。

この:

select m.mortal_zip as "Mortals in 44444" 
     ,p.payer_zip as "Payers in 44444" 
    from 
     (select count(am.zip_code) as mortal_zip 
     from address am 
     where trim(am.zip_code) = '44444' 
      and am.address_id in 
      (select mortal_address.address_id 
       from mortal_address 
       where mortal_address.mortal_id in 
        (select mortal.mortal_id 
        from mortal 
        ) 
      ) 
     ) m, 
     (select count(ap.zip_code) as payer_zip 
     from address ap 
     where trim(ap.zip_code) = '44444' 
      and ap.address_id in 
      (select payer_address.address_id 
       from payer_address 
       where payer_address.payer_id in 
        (select payer.payer_id 
         from payer 
        ) 
      ) 
     ) p; 

戻り値:

Mortals in 44444 Payers in 44444 
---------------- --------------- 
       3    0 

この:

select mortal_zip as "Mortals in 44444" 
     ,payer_zip as "Payers in 44444" 
    from 
     (select count(am.zip_code) as mortal_zip 
     from address am 
     join mortal_address 
      on mortal_address.address_id = am.address_id 
     join mortal 
      on mortal.mortal_id = mortal_address.mortal_id 
     where trim(am.zip_code) = '44444' 
     ) m, 
     (select count(ap.zip_code) as payer_zip 
     from address ap 
     join payer_address 
      on payer_address.address_id = ap.address_id 
     join payer 
      on payer.payer_id = payer_address.payer_id 
     where trim(ap.zip_code) = '44444' 
     ) p; 

戻り値:

Mortals in 44444 Payers in 44444 
---------------- --------------- 
       5    0 
+1

ここで行っている結合タイプは避けてください。デカルト結合を読んでください。 CROSS JOINを有効にしていますが、クエリの片側が空であるため結果が得られません。あなたがしたいのは、ベーステーブルを使用して、次にLEFT JOINを実行することです。これにより、データを抑制することなくNULL値を返すことができます。 –

+0

なぜ郵便番号をトリミングする必要がありますか?周囲に不必要なスペースがあるかも知っていますか?そのような場合は、次のようなものを使用する方が効率的です。where am.zip_code like '%44444%' - 可能な限り、関数内で列の値を折り返さないようにします。 – mathguy

+0

@mathguy郵便番号フィールドは、15文字のスペースを持つvarcharデータ型です。 –

答えて

0

は、私はあなたが必要な値を取得するにはUNIONでこれをやって、その後、単に値を合計することをお勧め:運のベスト

SELECT SUM(MORTAL_ZIP) AS MORTAL_ZIP, 
     SUM(PAYER_ZIP) AS PAYER_ZIP 
FROM (select COUNT(*) as mortal_zip, 
      0 as payer_zip 
     from address a 
     inner join mortal_address ma 
      on ma.address_id = a.address_id 
     inner join mortal m 
      on m.mortal_id = ma.mortal_id 
     where trim(a.zip_code) = '44444' 
     UNION ALL 
     select 0 as mortal_zip, 
      count(*) as payer_zip 
     FROM address a 
     inner join payer_address pa 
      on pa.address_id = a.address_id 
     inner join payer p 
      on p.payer_id = pa.payer_id 
     where trim(a.zip_code) = '44444') 

1

クエリは、JOINに3行の結果セットを含む空の結果セットを試行しています。もちろん、これは空の結果セットを返します。代わりに、あなたはCOUNTを取得する副選択を実行することができ自分自身、あるいは(S)

SELECT 
    COUNT(MA.address_id) AS "Mortals in 44444", 
    COUNT(PA.address_id) AS "Payers in 44444" 
FROM 
    Address A 
LEFT OUTER JOIN Mortal_Address MA ON MA.address_id = A.address_id 
LEFT OUTER JOIN Payer_Address PA ON PA.address_id = A.address_id 
WHERE 
    A.zip_code = '44444' 
-1

私はおそらくこのため、スタックオーバーフローを依頼する必要はありませんでしたが、ここでその私が求めていることの答えはあります。誰もがこのスレッドを手に入れることができるように助けてくれることを願っています。

select m.mortal_zip as "Mortals in 44444" 
     ,p.payer_zip as "Payers in 44444" 
    from 
     (select count(am.zip_code) as mortal_zip 
     from address am 
     where trim(am.zip_code) = '44444' 
      and am.address_id in 
      (select mortal_address.address_id 
       from mortal_address 
       where mortal_address.mortal_id in 
        (select mortal.mortal_id 
        from mortal 
        ) 
      ) 
     ) m, 
     (select count(ap.zip_code) as payer_zip 
     from address ap 
     where trim(ap.zip_code) = '44444' 
      and ap.address_id in 
      (select payer_address.address_id 
       from payer_address 
       where payer_address.payer_id in 
        (select payer.payer_id 
         from payer 
        ) 
      ) 
     ) p; 

私はちょうどcountをサブ選択に入れる必要がありました。ただ@TomHが言ったように。

+0

このクエリは、利益のために多くの作業を行っています。リストの最初の答えははるかに速くなります。実際には、2番目もそうです。 –

+0

@TGray私の目的のために、それは動作します。その小さなデータセットと私は時間がたっぷりでした。私はそれを改訂し、おそらくあなたが尊敬する回答の一つを受け入れます。すべて私は助けることができませんでしたが、単にそれを見て私のクエリの効率をどのように測定することができるか尋ねる。 –

+0

同じテーブルに対するカウントとサブクエリに基づいています。これは、せいぜいクエリのハッシュを引き起こし、オプティマイザが手を放つと、いくつかの主要なスキャンを引き起こします。個人的なものはありません。私は長い間クエリを書いてきました。非常に小さなデータセットをお持ちの場合、動作する可能性があります。関数ベースのインデックスを持たない限り、郵便番号のトリムは、その列のインデックスを無視します。さらに、郵便番号に対するデータの配信は小さくなるでしょう。 "in"句を追加すると、せいぜい部分スキャンに直面します。おそらくあなたの小さなデータセットの問題ではありません。 –