Sử dụng bí danh bên ngoài trong truy vấn con


11
|    payments    |  | transactions |  | transaction_items |
|:--------------:|  |:------------:|  |:-----------------:|
|       id       |  |      id      |  |         id        |
|      date      |  |    number    |  |   transaction_id  |
|     amount     |  |     date     |  |    description    |
| transaction_id |  |      val     |  |       price       |
                                      |      discount     |
                                      |      quantity     |

Tôi đang cố gắng hiển thị danh sách các khoản thanh toán được thực hiện trên các giao dịch và hiển thị số dư hiện tại sau mỗi khoản thanh toán. Dưới đây là một ví dụ về kết quả mong đợi

| 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    | 

và đây là truy vấn của tôi cho đến nay, nhưng có một lỗi trong mệnh đề 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

Xin lưu ý rằng tôi đang nhóm bởi p.datevì mối quan tâm của chúng tôi là tổng số thanh toán được thực hiện trong ngày.

Ai đó có thể xin vui lòng cho tôi biết tại sao tôi nhận được lỗi đó? Và có cách giải quyết nào để đạt được kết quả như mong đợi không?

Câu trả lời:


10

Hai lựa chọn lồng nhau trong truy vấn của bạn được gọi là bảng dẫn xuất . Một bảng dẫn xuất không có nghĩa là tương quan với các bộ dữ liệu khác tham gia truy vấn, do đó các tham chiếu bên ngoài đến chúng trong truy vấn lồng nhau không được phép.

Một cách để giải quyết vấn đề là viết lại truy vấn của bạn để di chuyển lựa chọn vi phạm sang bối cảnh cho phép tương quan. Trong trường hợp của bạn, bạn có thể di chuyển truy vấn con vi phạm sang mệnh đề 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 ở đây


Để hoàn thiện, tiêu chuẩn SQL thực sự có cú pháp cho phép tương quan cho các bảng dẫn xuất. Nó được gọi là tham gia bên . Từ quan điểm cú pháp, nó trông gần giống hệt như một phép nối thông thường, bạn chỉ cần thêm LATERALtừ khóa sau 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

Từ khóa được thêm vào tạo ra tất cả sự khác biệt, vì chỉ với từ khóa đó, một truy vấn lồng nhau mới được phép tham chiếu các bộ dữ liệu khác trong cùng một mệnh đề TỪ (ở bên trái của từ khóa THAM GIA gần đây nhất).

Các phép nối bên hiện đang được PostgreSQL và Oracle hỗ trợ. Một khái niệm tương tự với cú pháp hơi khác (và kém linh hoạt hơn) cũng được SQL Server hỗ trợ. Như bạn có thể đoán, MySQL hiện không hỗ trợ bất cứ thứ gì thuộc loại này.


MariaDB hỗ trợ các ứng dụng cửa sổ có thể thuận tiện cho việc chạy các vấn đề tổng thể như thế này: mariadb.com/kb/en/l Library / windows
fifts

Mainflow MySQL sẽ có chức năng cửa sổ trong phiên bản 8: dev.mysql.com/doc/refman/8.0/en/window-fifts.html Tôi đoán khi nào là năm nay, có thể là trong 6 tháng đầu tiên (xem xét như trên nói: "Dự thảo sẵn có trước chung: 2018-01-12").
ypercubeᵀᴹ

@McNets và Andriy Tôi đã làm cho nó hoạt động ngay bây giờ bằng cách sử dụng câu trả lời của bạn. Bạn đã giải thích nó tốt và với một số takeaways (từ khóa bên). Cảm ơn bạn!
Jaime Sangcap

Tôi rất vui lòng giúp đỡ.
McNets

@JaimeSangcap: Rất vui được giúp đỡ, chúc mừng.
Andriy M
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.