行项目表的总和 SQL 子查询
Posted
技术标签:
【中文标题】行项目表的总和 SQL 子查询【英文标题】:Sum of sums from tables of line items SQL Subquery 【发布时间】:2014-05-22 17:38:55 【问题描述】:我有 3 张桌子: 顾客 闭门器 已关闭的档案
每个都由一个客户 ID 字段链接。 CLOSEDORDERS 和 CLOSEDORDERSARCHIVES 是包含曾经售出的每张发票的每一行项目的表格。我试图为客户提供终生总数,但我被困在最后的总数上。这是我写的,它在两列中为每个表输出正确的总数(一些值为空):
SELECT CUSTOMERS.Company, CUSTOMERS.[Ship City], CUSTOMERS.[Ship State],
(SELECT SUM (CLOSEDORDERSARCHIVE.Quantity*CLOSEDORDERSARCHIVE.SellPrice)
FROM CLOSEDORDERSARCHIVE
WHERE CLOSEDORDERSARCHIVE.CustomerID = CUSTOMERS.ID) AS archiveTotal,
(SELECT SUM (CLOSEDORDERS.Quantity*CLOSEDORDERS.SellPrice)
FROM CLOSEDORDERS
WHERE CLOSEDORDERS.CustomerID = CUSTOMERS.ID) AS currentTotal
FROM CUSTOMERS, CLOSEDORDERSARCHIVE, CLOSEDORDERS
WHERE (((CUSTOMERS.Branch)=33));
当我搜索时,我发现这个答案看起来很相似,但我无法让它发挥作用,是因为总和是从表格中的行项目求和并按客户分组的吗?另外,这是我的第一个查询之一,有没有更有效的方法来编写/完成这个?
Sum of sums in different tables
【问题讨论】:
【参考方案1】:我们可以先把它分解成一个更简单的问题:把你需要的所有东西都放在一张桌子上。
如果求和所需的唯一列是数量和销售价格(当然还有 ID),您可以将它们合并到子查询中,然后计算它们的总和。子查询看起来像:
select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERSARCHIVE
UNION ALL
select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERS
之后,您可以从该子查询中进行选择并按客户 ID 分组,您将获得每个客户的总和:
select ID, SUM(Quantity*SellPrice) from(
select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERSARCHIVE
UNION ALL
select CustomerID as 'ID', Quantity as 'Quantity', SellPrice as 'SellPrice'
from CLOSEDORDERS
) as subq1
GROUP By ID
我认为这就是你所需要的。如果您希望显示客户名称和类似内容,您甚至可以将最后一个查询与表客户连接起来 =)
【讨论】:
当我尝试运行它时,我得到“FROM 子句中的语法错误。” 它说的是哪一行?我在这里找不到 sintax 错误 它突出显示第一个“UNION ALL”行。这是在 Access 中,我不知道这是否会有所不同 这是一个很好的解决方案,但它假定所有公司都已下订单。如果公司尚未下订单,则不会显示在结果中。我假设提问者仍然想列出它们,只是总共“0”。为了保证所有公司都被列出,不管订单如何,您可能必须从 CUSTOMERS 开始,并至少进行一次外部联接。看我的回答。 @Damieh - 是的,我错过了你答案的那一部分! jgiblets - 如果你这样做,记住它必须是一个外连接——在这种情况下是一个右外连接,你必须检查 NULL。【参考方案2】:我认为最不直观的解决方案是加入子查询(啊!)。这是一个(过于简化,请参阅下面的警告)示例:
SELECT
c.Company,
c.[Ship City],
c.[Ship State],
co.Total + coa.Total AS 'Grand Total'
FROM CUSTOMERS c
LEFT OUTER JOIN (
SELECT CustomerID, SUM(Quantity*SellPrice) as 'Total'
FROM CLOSEDORDERS
GROUP BY CustomerID
) AS 'co' ON c.ID = co.CustomerID
LEFT OUTER JOIN (
SELECT CustomerID, SUM(Quantity*SellPrice) as 'Total'
FROM CLOSEDORDERSARCHIVE
GROUP BY CustomerID
) AS 'coa' ON c.ID = coa.CustomerID
WHERE c.Branch = 33
在这种情况下,我们将创建两个中间表(co 和 coa),其中包含表中列出的每个客户的 CLOSEDORDERS 和 CLOSEDORDERSARCHIVE 的订单总数。
警告:如果某个公司的 CLOSEDORDERS 或 CLOSEDORDERSARCHIVE 中没有订单,则该公司的 co.Total(或 coa.Total)将为 NULL。您需要检查这一点,否则添加将是错误的(IIRC NULL + 数字 = NULL)。所以 SELECT 子句的 "co.Total" 和 "coa.Total" 表达式应该使用 COALESCE 或 CASE 语句来检查它。比如:
...COALESCE(co.Total,0) + COALESCE(coa.Total,0) AS 'Grand Total'...
【讨论】:
IIRC SQL server 不喜欢子查询后的AS
,所以Access 可能也是这样。它是可选的,因此如果它给您带来麻烦,您可以将其删除:) 'co' ON c.ID = co.CustomerID
。
SQL Server 确实喜欢子查询名称前的“as”。我一直这样做,相信我 =)以上是关于行项目表的总和 SQL 子查询的主要内容,如果未能解决你的问题,请参考以下文章
在没有 FROM 子查询的 JOIN 中写入具有总和限制的 SQL 计数