我已经提供了表的摘要,并且在 SQL 方面有了良好的开端,但我一直在弄清楚如何限制返回的项目数。我应该能够选择一个或多个条款,并仅从这些条款中收回应付余额。
学生应该有 1 条记录,他们可以在多个学期内进行多次预订,但付款并不特定于预订,而是特定于学生。这就是让我失望的部分。
表结构、日期和 SQL 的开始如下。有人可以帮我吗?此结果不应显示 Sue Smith 第 3 学期支付的 500 美元。
我正在使用 PostgreSQL,但我认为这是一个非常基本的问题,不需要任何特定于 Postgres 的内容。
当前结果集:
Student ID Last First Total Fees Reservation Count Amount Paid Amount Due
123456 Jones Amy 50 1 50 0
412365 Smith Sue 100 3 545 -445
741258 Anderson Jon 50 1 0.00 50.00
963258 Holmes Fred 100 2 30 70
架构:
SET search_path TO temp, public;
CREATE TABLE term
(term_id SERIAL PRIMARY KEY,
term_title VARCHAR(100));
CREATE TABLE student
(student_id SERIAL PRIMARY KEY,
student_sis_id VARCHAR(15),
student_first_name VARCHAR(30),
student_last_name VARCHAR(100));
CREATE TABLE reservation
(reservation_id SERIAL PRIMARY KEY,
student_id INTEGER REFERENCES student ON UPDATE CASCADE,
term_id INTEGER REFERENCES term ON UPDATE CASCADE,
reservation_fee_amount NUMERIC DEFAULT 0.00);
CREATE TABLE payment
(payment_id SERIAL PRIMARY KEY,
student_id INTEGER REFERENCES student ON UPDATE CASCADE,
term_id INTEGER REFERENCES term ON UPDATE CASCADE,
payment_cash_amount NUMERIC,
payment_credit_card_amount NUMERIC,
payment_check_amount NUMERIC);
INSERT INTO term VALUES (DEFAULT, 'SESSION 1');
INSERT INTO term VALUES (DEFAULT, 'SESSION 2');
INSERT INTO term VALUES (DEFAULT, 'SESSION 3');
INSERT INTO student VALUES (DEFAULT, 412365, 'Sue', 'Smith');
INSERT INTO student VALUES (DEFAULT, 123456, 'Amy', 'Jones');
INSERT INTO student VALUES (DEFAULT, 741258, 'Jon', 'Anderson');
INSERT INTO student VALUES (DEFAULT, 963258, 'Fred', 'Holmes');
INSERT INTO reservation VALUES (DEFAULT, 1, 1, 50);
INSERT INTO reservation VALUES (DEFAULT, 1, 2, 50);
INSERT INTO reservation VALUES (DEFAULT, 2, 1, 50);
INSERT INTO reservation VALUES (DEFAULT, 3, 2, 50);
INSERT INTO reservation VALUES (DEFAULT, 4, 1, 50);
INSERT INTO reservation VALUES (DEFAULT, 4, 2, 50);
INSERT INTO reservation VALUES (DEFAULT, 1, 3, 50);
INSERT INTO payment VALUES (DEFAULT, 1, 1, 25, 0, 0);
INSERT INTO payment VALUES (DEFAULT, 1, 1, 0, 20, 0);
INSERT INTO payment VALUES (DEFAULT, 2, 1, 25, 25, 0);
INSERT INTO payment VALUES (DEFAULT, 4, 1, 10, 10, 10);
INSERT INTO payment VALUES (DEFAULT, 1, 3, 500, 0, 0);
查询:
SELECT
student.student_sis_id AS "Student ID",
student.student_last_name AS Last,
student.student_first_name AS First,
SUM(reservation.reservation_fee_amount) AS "Total Fees",
(
SELECT COUNT(reservation.reservation_id)
FROM reservation
WHERE student.student_id = reservation.student_id
) AS "Reservation Count",
(
SELECT
COALESCE(SUM(
payment.payment_check_amount
+ payment.payment_cash_amount
+ payment.payment_credit_card_amount
), 0.00)
FROM payment
WHERE payment.student_id = student.student_id
) AS "Amount Paid",
SUM(reservation.reservation_fee_amount) - (
SELECT
COALESCE(SUM(
payment.payment_check_amount
+ payment.payment_cash_amount
+ payment.payment_credit_card_amount
), 0.00)
FROM payment WHERE payment.student_id = student.student_id
) AS "Amount Due"
FROM
student
INNER JOIN reservation ON student.student_id = reservation.student_id
WHERE reservation.term_id IN (1,2)
GROUP BY
student.student_id,
student.student_sis_id,
student.student_last_name,
student.student_first_name
ORDER BY
student.student_sis_id
;
最佳答案
这是我的查询的更新版本:
SELECT
s.student_sis_id AS "Student ID",
s.student_last_name AS Last,
s.student_first_name AS First,
SUM(r.reservation_fee_amount) AS "Total Fees",
COUNT(r.reservation_id) AS "Reservation Count",
COALESCE(
SUM(
p.payment_check_amount
+ p.payment_cash_amount
+ p.payment_credit_card_amount
), 0.00
) AS "Amount Paid",
SUM(r.reservation_fee_amount) - (
COALESCE(
SUM(
p.payment_check_amount
+ p.payment_cash_amount
+ p.payment_credit_card_amount
), 0.00
)
) AS "Amount Due"
FROM
student s
INNER JOIN reservation r ON s.student_id = r.student_id
LEFT JOIN payment p ON p.student_id = r.student_id AND p.term_id = r.term_id
WHERE r.term_id IN (1,2)
GROUP BY
s.student_id,
s.student_sis_id,
s.student_last_name,
s.student_first_name
ORDER BY
s.student_sis_id
;
看点:
我包括了
payments
在主(外部)查询中以避免子查询连接类型为
LEFT [OUTER] JOIN
,所以缺少任何payment
rows 不会阻止其他数据出现在结果集中连接条件包括
term_id
(我认为这基本上就是你迷路的地方)最后我使用了短表别名来提高可读性。
我希望这就是您所追求的。
关于SQL 查询到期余额而不对所有选择进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12230180/