SUM() 只取一行
SUM() taking from only one row
两个表:"S"(对于 "Services")和 "Payments"。它们通过被引用为外键的 "S"."ID-S" 联系在一起:"Payments"."S".
我正在尝试为 "add payment" 表单中的下拉列表创建查询,但由于我希望允许部分付款,因此我想减去已支付的已绑定付款的总和到给定的 "ID-S"。但是,我似乎无法隐藏通过多次付款支付的服务。
以下是我当前的代码,仅使用 "services" 类别之一(在本例中为发票):
SELECT "S"."Invoice" || ' for $' || "S"."Price" -
IIF("Payments"."S" IS NULL, 0, SUM("Payments"."Amount")
AS "To-Pay", "ID-S"
FROM "S"
LEFT OUTER JOIN "Payments" ON "S"."ID-S" = "Payments"."S"
GROUP BY "S"."Invoice", "S"."Price", "Payments"."Amount", "Payments"."S", "S"."ID-S"
HAVING "Payments"."S" IS NULL OR
SUM("Payments"."Amount") < "S"."Price"
它应该显示,例如:
- 2018 年 1 月 1 日只需 400 美元
- 2018 年 2 月 1 日只需 1050 美元
- 6/8/2018 750 美元
等,价格为剩余的价格。它根本不应该显示完全付清的发票。
据我所知,问题是 SUM("Payments"."Amount")
没有将所有 "Amount" 列与匹配的 "S-ID" 相加,它只需要 [=48] =] 来自给定的行。这对我一点帮助都没有,因为如果,比如说,一张 3000 美元的发票分别以 1000 美元和 2000 美元的两次付款还清,则该列表不仅仍会显示发票,而且会显示两次 - 一次剩余 2000 美元,一次还剩 1000 美元。
我正在将 LibreOffice Base 与 Firebird 结合使用。
编辑:根据进一步的数据输入,我发现了一个如上所述显示双重支付的案例(两次不同 "prices remaining"),而另一个这样的双重支付显示一次为“$0”价格,可能是因为正好对半分割?
也许您应该 extract/encapsulate 分组到一个单独的查询中。没有看到示例数据很难推理,但请尝试使用 Derived Table
或 Common Table Expression
.
下面只是最上面的 google 个结果,可以让您有个大概的了解。
- https://www.mssqltips.com/sqlservertip/1042/using-derived-tables-to-simplify-the-sql-server-query-process/
- https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-2017
Firebird 专用手册位于 https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-dml-select.html
此外 - 您真的需要在服务器上完成这一切吗,比如连接文本字符串?通常它是在客户端制作的,带有本地化和字体装饰等等。
要尝试的模式:
WITH Parts AS (
SELECT ID_S, Sum(Amount) as Done
FROM Payments
GROUP BY 1
)
SELECT S.Invoice, S.Price - COALESCE( Parts.Done, 0)
FROM Services S
LEFT JOIN Parts ON S.ID = Parts.ID_S
-- WHERE S.Price > COALESCE( Parts.Done, 0)
WHERE S.Price > Parts.Done OR Parts.Done IS NULL
或相等模式
SELECT S.Invoice, S.Price - COALESCE( Parts.Done, 0)
FROM Services S
LEFT JOIN ( SELECT ID_S, Sum(Amount) as Done FROM Payments GROUP BY 1)
AS Parts ON S.ID = Parts.ID_S
-- WHERE S.Price > COALESCE( Parts.Done, 0)
WHERE S.Price > Parts.Done OR Parts.Done IS NULL
两个表:"S"(对于 "Services")和 "Payments"。它们通过被引用为外键的 "S"."ID-S" 联系在一起:"Payments"."S".
我正在尝试为 "add payment" 表单中的下拉列表创建查询,但由于我希望允许部分付款,因此我想减去已支付的已绑定付款的总和到给定的 "ID-S"。但是,我似乎无法隐藏通过多次付款支付的服务。
以下是我当前的代码,仅使用 "services" 类别之一(在本例中为发票):
SELECT "S"."Invoice" || ' for $' || "S"."Price" -
IIF("Payments"."S" IS NULL, 0, SUM("Payments"."Amount")
AS "To-Pay", "ID-S"
FROM "S"
LEFT OUTER JOIN "Payments" ON "S"."ID-S" = "Payments"."S"
GROUP BY "S"."Invoice", "S"."Price", "Payments"."Amount", "Payments"."S", "S"."ID-S"
HAVING "Payments"."S" IS NULL OR
SUM("Payments"."Amount") < "S"."Price"
它应该显示,例如:
- 2018 年 1 月 1 日只需 400 美元
- 2018 年 2 月 1 日只需 1050 美元
- 6/8/2018 750 美元
等,价格为剩余的价格。它根本不应该显示完全付清的发票。
据我所知,问题是 SUM("Payments"."Amount")
没有将所有 "Amount" 列与匹配的 "S-ID" 相加,它只需要 [=48] =] 来自给定的行。这对我一点帮助都没有,因为如果,比如说,一张 3000 美元的发票分别以 1000 美元和 2000 美元的两次付款还清,则该列表不仅仍会显示发票,而且会显示两次 - 一次剩余 2000 美元,一次还剩 1000 美元。
我正在将 LibreOffice Base 与 Firebird 结合使用。
编辑:根据进一步的数据输入,我发现了一个如上所述显示双重支付的案例(两次不同 "prices remaining"),而另一个这样的双重支付显示一次为“$0”价格,可能是因为正好对半分割?
也许您应该 extract/encapsulate 分组到一个单独的查询中。没有看到示例数据很难推理,但请尝试使用 Derived Table
或 Common Table Expression
.
下面只是最上面的 google 个结果,可以让您有个大概的了解。
- https://www.mssqltips.com/sqlservertip/1042/using-derived-tables-to-simplify-the-sql-server-query-process/
- https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-2017
Firebird 专用手册位于 https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-dml-select.html
此外 - 您真的需要在服务器上完成这一切吗,比如连接文本字符串?通常它是在客户端制作的,带有本地化和字体装饰等等。
要尝试的模式:
WITH Parts AS (
SELECT ID_S, Sum(Amount) as Done
FROM Payments
GROUP BY 1
)
SELECT S.Invoice, S.Price - COALESCE( Parts.Done, 0)
FROM Services S
LEFT JOIN Parts ON S.ID = Parts.ID_S
-- WHERE S.Price > COALESCE( Parts.Done, 0)
WHERE S.Price > Parts.Done OR Parts.Done IS NULL
或相等模式
SELECT S.Invoice, S.Price - COALESCE( Parts.Done, 0)
FROM Services S
LEFT JOIN ( SELECT ID_S, Sum(Amount) as Done FROM Payments GROUP BY 1)
AS Parts ON S.ID = Parts.ID_S
-- WHERE S.Price > COALESCE( Parts.Done, 0)
WHERE S.Price > Parts.Done OR Parts.Done IS NULL