| payments | | transactions | | transaction_items |
|:--------------:| |:------------:| |:-----------------:|
| id | | id | | id |
| date | | number | | transaction_id |
| amount | | date | | description |
| transaction_id | | val | | price |
| discount |
| quantity |
トランザクションで行われた支払いのリストを表示し、各支払い後に現在の残高を表示しようとしています。以下は期待される結果の例です
| number | DATE(p.date) | total | paid | balance |
| 1355 | 2016-10-31 | 899.00 | 450.00 | 449.00 |
| 1355 | 2016-12-06 | 899.00 | 449.00 | 0.00 |
| 1359 | 2016-09-28 | 4045.00 | 1515.00 | 2530 |
| 1359 | 2016-10-24 | 4045.00 | 35.00 | 2495.00 |
| 1361 | 2016-09-28 | 1548.00 | 1548.00 | 0.00 |
これがこれまでの私のクエリですが、where句にエラーがあります
select
t.number,
DATE(p.date),
ti.total 'total',
SUM(p.amount) 'paid',
ti.total - paid.total 'balance'
from payments p
left join transactions t
on p.transaction_id = t.id
left join (
select inner_ti.transaction_id, sum((inner_ti.price - inner_ti.discount) * inner_ti.quantity) 'total'
from transaction_items inner_ti
group by inner_ti.transaction_id
) ti on t.id = ti.transaction_id
left join (
select inner_p.transaction_id, sum(inner_p.amount) 'total'
from payments inner_p
where inner_p.date <= p.date -- error unknown column p.date
group by inner_p.transaction_id
) paid on t.id = paid.transaction_id
group by t.number, DATE(p.date), ti.total, paid.total
order by DATE(p.date) ASC
私たちはp.date
でグループ化していることに注意してください。私たちの懸念は、その日以内に行われた支払いの合計です。
誰かがそのエラーを受け取っている理由を誰かに教えてもらえますか?そして、期待される結果を達成するための回避策はありますか?
クエリ内の2つのネストされた選択は、派生テーブルと呼ばれます。派生テーブルは、クエリに参加している他のデータセットと相関することを意図していないため、ネストされたクエリでそれらを参照することはできません。
問題を解決する1つの方法は、問題のある選択を相関が許可されているコンテキストに移動するようにクエリを書き直すことです。あなたのケースでは、問題のあるサブクエリをSELECT句に移動できます。
select t.number,
DATE(p.date),
ti.total 'total',
SUM(p.amount) 'paid',
ti.total - (select sum(inner_p.amount)
from payments inner_p
where inner_p.transaction_id = p.transaction_id
and inner_p.date <= p.date
) 'balance'
from payments p
left join transactions t
on p.transaction_id = t.id
left join (
select inner_ti.transaction_id,
sum((inner_ti.price - inner_ti.discount) * inner_ti.quantity) 'total'
from transaction_items inner_ti
group by inner_ti.transaction_id
) ti
on t.id = ti.transaction_id
group by t.number, DATE(p.date), ti.total, 'balance'
order by DATE(p.date) ASC;
rextester ここ
完全を期すために、SQL標準には実際には派生テーブルの相関を可能にする構文があります。 ラテラルジョインと呼ばれます。構文の観点からは、通常の結合とほとんど同じように見えます。LATERAL
の後にJOIN
キーワードを追加するだけです。
…
left join lateral (
select inner_p.transaction_id, sum(inner_p.amount) 'total'
from payments inner_p
where inner_p.date <= p.date -- this outer reference would be valid
group by inner_p.transaction_id
) paid on t.id = paid.transaction_id
…
ネストされたクエリは、同じFROM句(最新のJOINキーワードの左側)の他のデータセットを参照することが許可されているため、追加されたキーワードはすべての違いをもたらします。
現在、ラテラル結合はPostgreSQLとOracleでサポートされています。 SQL Serverでは、構文がわずかに異なる(柔軟性が低い)同様の概念もサポートされています。ご想像のとおり、現在、MySQLはそのようなものをサポートしていません。