2009-08-06 13 views
6

私は以下のDBデザインを継承しました。テーブルは以下のとおりです。合計を得るために3つのテーブルのSQL JOIN、GROUP BY

customers 
--------- 
customerid 
customernumber 

invoices 
-------- 
invoiceid 
amount 

invoicepayments 
--------------- 
invoicepaymentid 
invoiceid 
paymentid 

payments 
-------- 
paymentid 
customerid 
amount 

私のクエリが与えられたCUSTOMERNUMBERためinvoiceid、(請求書テーブル内の)請求額、及び量により(請求額マイナス請求書に向けて行われている任意の支払いを)返す必要があります。顧客は複数の請求書を持っているかもしれません。

次のクエリでは、複数の支払いが請求書に行われたときに、レコードを複製する私を与える:

SELECT i.invoiceid, i.amount, i.amount - p.amount AS amountdue 
FROM invoices i 
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid 
LEFT JOIN payments p ON ip.paymentid = p.paymentid 
LEFT JOIN customers c ON p.customerid = c.customerid 
WHERE c.customernumber = '100' 

どのように私はこの問題を解決することができますか?

+0

1つの請求書に対していくつの請求書支払い行が存在する可能性がありますか? 各支払いIDにはいくつの支払いが存在する可能性がありますか? –

答えて

10

私はあなたを得たが、これはあなたが探しているものかもしれないことを確認していない:

SELECT i.invoiceid, sum(case when i.amount is not null then i.amount else 0 end), sum(case when i.amount is not null then i.amount else 0 end) - sum(case when p.amount is not null then p.amount else 0 end) AS amountdue 
FROM invoices i 
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid 
LEFT JOIN payments p ON ip.paymentid = p.paymentid 
LEFT JOIN customers c ON p.customerid = c.customerid 
WHERE c.customernumber = '100' 
GROUP BY i.invoiceid 

これはあなたに、各請求書の複数の支払いの行が存在する場合には金額の合計を得るでしょう

+1

あなたは 'coalesce'または' isnull'に 'amount'カラムをラップするべきでしょう。 MS-SQLでは、任意のNULL値。 'left join'sから、全体がNULLに評価されます。私はいくつかのSQL方言がNULL == 0を許していることを知っていますが、それは宗教的な戦争につながります... – Adrien

+0

SQL dbms hesを使っているかどうかわからないので、 "case"節を追加しました。ありがとう! –

+0

個人的には、請求書額が主キーであり、請求書表の金額がNOT NULLに制限されており、代わりにi.amountをGROUP BY句に追加すると仮定して、請求書金額を合計しません。 –

2

ファーストInvoiceテーブルにCustomerIdがあるべきではありませんか?つまり、支払いがまだない請求書に対してこのクエリを実行することはできません。請求書の支払いがない場合、その請求書は外注の場合でもクエリの出力に表示されません。

また、顧客が支払いを行うと、添付する請求書?唯一の方法が支払で到着したスタブ上のInvoiceIdである場合、注文した顧客ではなく、支払いを行った顧客に請求書を関連付ける(おそらく不適切です)...。 (場合によっては、サービスを注文した顧客以外の人が請求書を支払うことがあります)

+0

これは本当に良い点です。あなたの最後の声明は、ポスターの会社で真実であるかもしれないし、そうでないかもしれないビジネスルールであると私は言います。全体的に見れば、デザインは面倒です。外側の結合の使用には何の意味もありません。述語では、顧客 –

4

返信いただきありがとうございます!

Saggi Malachi、そのクエリは複数の支払いがある場合には残念ながら請求書の金額を合計します。 $ 18と$ 12という39ドルの請求書に2つの支払いがあるとします。あなたがになってしまいます

1 39.00 9.00 

:だから、むしろのように見える結果に終わるよりも

1 78.00 48.00 

チャールズBretana、最も単純なクエリのIまでの私のクエリをトリミングする過程で(愚かに)顧客と請求書の間のリンクを提供する追加の表customerinvoicesは省略されました。これは、支払が行われていない請求書を表示するために使用することができます。あなたたちは同意するだろう

SELECT DISTINCT i.invoiceid, i.amount, ISNULL(i.amount - p.amount, i.amount) AS amountdue 
FROM invoices i 
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid 
LEFT JOIN customerinvoices ci ON i.invoiceid = ci.invoiceid 
LEFT JOIN (
    SELECT invoiceid, SUM(p.amount) amount 
    FROM invoicepayments ip 
    LEFT JOIN payments p ON ip.paymentid = p.paymentid 
    GROUP BY ip.invoiceid 
) p 
ON p.invoiceid = ip.invoiceid 
LEFT JOIN payments p2 ON ip.paymentid = p2.paymentid 
LEFT JOIN customers c ON ci.customerid = c.customerid 
WHERE c.customernumber='100' 

かなり苦労した後、私は次のクエリは、私がそれを必要とするものを返すことはないでしょうか?

+0

から行が返される必要があるので、それはうまくいきます。 – RiddlerDev

2

私は、同じテーブルからさまざまな集計値を取得するためのヒントを持っています。

私は、ユーザとテーブルを持つテーブルを持っており、ユーザが獲得するポイントを持っているとします。したがって、それらの間の接続は1:N(1人のユーザー、多数のポイントレコード)です。

テーブル 'ポイント'には、ユーザーがポイントを取得した情報(ログイン、バナーをクリックするなど)も保存されます。そして、すべてのユーザーをSUM(points)で注文し、次にSUM(points WHERE type = x)で注文したいと思います。つまり、ユーザーが持っているすべてのポイントと、ユーザーが特定のアクション(ログインなど)を得たポイントの順に並べ替えられます。

SQLは次のようになります。

SELECT SUM(points.points) AS points_all, SUM(points.points * (points.type = 7)) AS points_login 
FROM user 
LEFT JOIN points ON user.id = points.user_id 
GROUP BY user.id 

本の美しさは、内側括弧は、それが等しいwheteherに応じて、このようにして、0または1で与えられるポイント値を乗算する0または1のいずれかに評価SUM(points.points * (points.type = 7))であります私たちが望むポイントのタイプに