Sql 对列求和,对行进行计数,使用多个表一起显示数据
我有一个复杂的SQL问题,如下表和数据所示: 订单表:Sql 对列求和,对行进行计数,使用多个表一起显示数据,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个复杂的SQL问题,如下表和数据所示: 订单表: OrderId ClientId CompanyId -------------------------------- 25 2 NULL 26 NULL 1 27 3 NULL 28 3 NULL 29 NULL 3 Billing table
OrderId ClientId CompanyId
--------------------------------
25 2 NULL
26 NULL 1
27 3 NULL
28 3 NULL
29 NULL 3
Billing table Forwards table
OrderId Amount PaidFull OrderId Amount PaidFull
-------------------------- ---------------------------
25 $100 False 26 $25 False
26 $50 False 27 $50 False
27 $100 False 27 $50 False
28 $100 False 29 $50 False
29 $100 True
Client table Company table
ClientId ClientName CompanyId CompanyName
----------------------- ---------------------------
1 AClient 1 ACompany
2 BClient 2 BCompany
3 CClient 3 CCompany
我想在下面这样的表格中显示数据,每个公司或客户的总账单合计和行计数。每个公司或客户转发汇总和计数的行,并按照客户和公司名称的组合按字母顺序排列:
Billing Qty Forwards Qty Client/Company Name
--------------------------------------------------
$50 1 $25 1 ACompany
$100 1 $0 0 BClient
$200 2 $100 2 CClient
$0 0 $50 1 CCompany
问题是,使用下面的SQL查询,我得到了重复的值,对账单表求和,因为它对账单表orderid29求和$100,尽管它标记为PaidFull=True。另外,它不是按客户表和公司表的组合按字母顺序排序,而是先将它们分开,然后再排序
Select
Sum(b.Amount) As TotalAmount,
Count(b.Amount) As Count1,
Sum(f.Amount) As TotalAmountf,
Count(f.Amount) As Count2,
d.ClientName, c.CompanyName
From
Orders a
Left Join
Billing b On a.OrderId = b.OderId And b.PaidFull = 'False'
Left Join
Forwards f On a.OrderId = f.OderId And f.PaidFull = 'False'
Left Join
Client d On a.ClientId = d.ClientId
Left Join
Company c On a.CompanyId = c.CompanyId
Where
(b.FaidFull = 'False' Or f.PaidFull = 'False')
Group by
ClientName, CompanyName
Order by
ClientName, CompanyName
以下是您如何做到这一点:
select (case when cmp.CompanyName is null then c.ClientName else cmp.CompanyName end) "Client/Company Name"
, sum(b.Amount) Billing
, max(b.billingCount) QTY
, sum(f.Amount) Forwards
, max(f.forwardsCount) QTY
from orders o
join Clients c
on c.ClientId = o.ClientId
join Company cmp
on cmp.CompanyId = o.CompanyId
join ( select OrderId , sum(amount) amount , count(*) billingCount
from Billing b
group by orderId
) b
on b.OrderId = o.OrderId
join ( select OrderId , sum(amount(*) amount , count(*) forwardsCount
from forwards f
group by OrderId
) f
on f.OrderId = o.OrderId
group by (case when cmp.CompanyName is null then c.ClientName else cmp.CompanyName end)
虽然我不确定您的
账单
和转发
的表结构,但实现这一点的最简单方法是使用CTE首先对这两个表中的所有值求和,然后在最终查询中使用这些值,如下所示:
WITH TotalBilling
AS
(
SELECT
OrderId
,SUM(Amount) Amount
FROM
Billing
WHERE
PaidFull = 'FALSE'
GROUP BY
OrderId
),
TotalForwards
AS
(
SELECT
OrderId
,SUM(Amount) Amount
FROM
Forwards
WHERE
PaidFull = 'FALSE'
GROUP BY
OrderId
)
SELECT
SUM(B.Amount) AS Billing
,COUNT(B.OrderId) AS Qty
,SUM(F.Amount) AS Forwards
,COUNT(F.OrderId) AS Qty
,COALESCE(Cl.ClientName, Co.CompanyName) AS "Client / Company Name"
FROM
Orders O
LEFT JOIN Clients Cl
ON O.ClientId = Cl.ClientId
LEFT JOIN Companies Co
ON O.CompanyId = Co.CompanyId
LEFT JOIN TotalBilling B
ON B.OrderId = O.OrderId
LEFT JOIN TotalForwards F
ON F.OrderId = O.OrderId
GROUP BY
COALESCE(Cl.ClientName, Co.CompanyName)
ORDER BY
COALESCE(Cl.ClientName, Co.CompanyName)
是一个SqlFiddle,显示了它的外观。我不确定我是否理解
账单
和转发
表-如何在转发表中为相同的订单ID设置两个条目
(同样的情况会发生在账单上吗?可以想象,会出现什么情况,你的查询应该如何处理?你的答案是有效的。我只是在分组后加了一句,“Sum(B.Amount)>0或Sum(F.Amount)>0”为了不选择PaidFull=True的行。因为选择了PaidFull=True的行。为了回答您的问题,是的,账单和转发表中可能有多个相同的OrderID。从现在开始,这就可以工作了,我希望保持这种状态!我真的不确定您为什么需要它,因为它应该在CTEs.我在示例数据集中使用了额外的HAVING
子句,它返回了相同的表。但是,假设您的生产数据需要它,我很高兴它能为您工作,只是不确定您为什么需要添加它。