2

SELECT複数の 1 対多のテーブルを結合するクエリを作成しようとしています。disbursementsという名前のテーブルには、 contactsLEFT JOIN という名前のテーブルへのと(連絡先には多くの支払いがある可能性があるため) と、 pledges という名前のテーブルへの の両方が あります(誓約 (支払いの約束) は複数の支払い (実際の支払い) を持つことができるため)。LEFT JOIN

私の質問は、連絡先、そのプレッジ、およびプレッジ残高 (プレッジから差し引かれたプレッジに対する支払いの合計) をリストするレコードを取得するにはどうすればよいですか?

これが私がこれまでに得たものです:

SELECT *, (p.pl_amount - SUM(disb_amount)) as balance FROM disbursements d
LEFT JOIN contacts c on c.c_no = d.c_no
LEFT JOIN  pledges p on d.pl_no = p.pl_no 
GROUP BY d.disb_no
HAVING balance > 500
ORDER BY c.c_last

前もって感謝します

4

2 に答える 2

0

おそらく、支払い/誓約がない場合でも連絡先を取得したいので、contactsテーブルをFROMaではなく句に配置することをお勧めします。LEFT JOIN

また、誓約残高が>の連絡先のみが必要なように見えるため、誓約がない、または残高が>の連絡先も取得する場合を除いて500、aLEFT JOINは必要ありません500。代わりに通常の(内部)を使用しましたJOIN

これを試して:

SELECT    c.*,
          p.*,
          COALESCE(p.pl_amount - pd.disb_sum, 0) AS pledge_balance
FROM      contacts c
LEFT JOIN disbursements d ON c.c_no = d.c_no
LEFT JOIN pledges p ON d.pl_no = p.pl_no
LEFT JOIN (
          SELECT   pl_no, SUM(disb_amount) AS disb_sum
          FROM     disbursements
          GROUP BY pl_no
          ) pd ON p.pl_no = pd.pl_no
WHERE     p.pl_no IS NULL OR
          p.pl_amount - pd.disb_sum > 500
ORDER BY  c.c_last
于 2012-07-31T20:46:06.950 に答える
0

この問題を単純化できると思います。私の理解が正しければ、あなたの支払いはあなたの誓約に依存します(誓約がない場合、支払いはありません)。これが true の場合、次のようなことができます。

select 
    p.pl_no, p.pl_amount - sum(disb_amount) as balance
from 
    pledges as p
    left join disbursements as d on p.pl_no = d.pl_no
group by
    p.pl_no
having
    p.pl_amount - sum(disb_amount) > 500;

完全な情報 (連絡先、誓約、支払い) が必要な場合は、これを多段階の問題と考える必要があります。

  1. 最初に誓約の残高が必要です
  2. 誓約に関連付けられた連絡先が必要です
  3. このレコードの完全な情報が必要です

したがって、上記のクエリは、ステップ 1 に必要な情報を提供します。この情報を使用して一時テーブルを作成できます。

Create temporary table temp_pledge_balance
select 
    p.pl_no, p.pl_amount - sum(disb_amount) as balance
from 
    pledges as p
    left join disbursements as d on p.pl_no = d.pl_no
group by
    p.pl_no;

次のステップをスピードアップするために、このテーブルにインデックスを付けることをお勧めします。

Alter table temp_pledge_balance
    add index pl_no (pl_no);

次に、ステップ 2 を実行します。

create temporary table temp_contacts
select c.*, p.pl_no
from
    temp_pledge_balance as pb
    inner join pledges as p on pb.pl_no=p.pl_no
    inner join contacts as c on p.c_no = c.c_no;
alter temp_contacts
    add index c_no(c_no);

最後に、ステップ 3:

select
   tc.*, pb.*, p.*, d.*
from
   temp_contacts as tc
   left join disbursements as d on tc.c_no = d.c_no
   left join pledges as p on d.pl_no = p.pl_no
   left join temp_pledge_balance as pb on p.pl_no = pb.p_no
where
   pb.balance > 500

トリッキーな解決策ですが、役立つかもしれません。

于 2012-07-31T20:53:36.057 に答える