2

我有一个类似于这样的表数据结构:

房东桌

Id    Name        Email
```````````````````````
1     J Johnson    ...
2     R Kelly      ...

属性表

Id    Address    Rent    LandlordId
```````````````````````````````````
1    ....        400    1
2    ....        600    1
3    ....        750    2

保养表

Id    Details   Cost    MaintenanceDate    PropertyId
`````````````````````````````````````````````````````
1    ....        25     20/12/2012         1
2    ....        120    22/12/2012         2
3    ....        35     24/12/2012         3

本质上,房东有多个房产。每个月,我需要为房东开具发票,其中包括他的所有房产,对他的房产进行的所有维护。为了计算我需要付给房东多少钱,我需要将他所有房产的租金相加,然后减去他当月所有维护费用的总和。

因此,应支付给房东的金额 L = Sum(L 的房产租金) - Sum(L 在本月内所有房产的维护费用)

我正在使用 Telerik 报告,我认为我可以通过一些巧妙的分组来实现它,但那是在浪费我的时间,所以我现在将尝试使用 SQL 和子报告来实现它。

我正在尝试的 SQL 查询是这样的:

 SELECT l.Name, p.[Address], p.Rent, c.Details, c.Cost,
(select Rent From Property where Id = p.Id) - 
    (select SUM(cost) from CarriedOutJobs where PropertyId = p.Id) 
    as PayableToLandlord
FROM Landlord l JOIN PROPERTY p ON p.LandlordId = l.Id
LEFT OUTER JOIN Maintenance c ON c.PropertyId = p.Id
ORDER BY l.Fullname

这似乎无法正常工作,因为它会产生多个字段

因为我要将报告分解为子报告,所以我想我会先获取房东的详细信息,但即使在这种情况下,我仍然需要计算应支付给房东的金额。所以我将查询重写为:

SELECT distinct l.Name,
(SELECT SUM(Rent) FROM PROPERTY WHERE LandlordId = l.Id) - 
    (SELECT COALESCE(SUM(cost), 0)
    FROM CarriedOutJobs WHERE PropertyId = p.Id) AS     PayableToLandlord
FROM Landlord l 
JOIN PROPERTY p ON p.LandlordId = l.Id 
ORDER BY l.Fullname

我认为这行得通,但即使我使用了 distinct,这似乎会产生一个PayableToLandlord数量不同的重复行,我似乎无法弄清楚为什么。

请问有没有办法在一个查询中选择所有房东、他们的财产以及应付给他们的金额?

为了简单起见,我在这里删除了 date where 子句。

谢谢。

4

3 回答 3

6

我建议保持简单并使用子查询,因为这些很容易弄清楚发生了什么。希望您可以在报告中或非常简单地作为附加返回列进行减法等。您应该将任何日期参数作为变量传递给子查询(可能)。

SELECT Landlord.Id as LandlordId, Landlord.Name, 
       ISNULL(TotalRent,0) AS TotalRent, 
       ISNULL(TotalCost,0) AS TotalCost
FROM Landlord
LEFT JOIN 
    (SELECT SUM(Rent) as TotalRent, LandLordId 
     FROM Property
     GROUP BY LandLordId) Rents
ON Landlord.Id = Rents.LandlordId
LEFT JOIN 
    (SELECT LandLordId,SUM(Cost) AS TotalCost
     FROM Property
     INNER JOIN Maintenance
        ON Property.Id = Maintenance.PropertyId
     GROUP BY LandLordId
     ) MaintenanceCosts
ON Landlord.Id = MaintenanceCosts.LandlordId
ORDER BY Landlord.Name

刚刚注意到你还写道:

请问有没有办法在一个查询中选择所有房东、他们的财产以及应付给他们的金额?

您可以进一步加入属性列表,但最终会在每一行上重复总和。只要您不尝试在您的报告包中求和它就可以了。

如果您确实想要房产详细信息,那么我的建议是提取每个房产的租金和成本,然后在报告包中计算总和/净值。

于 2012-12-24T17:18:56.813 回答
1

这是一个较短的查询:请发表评论。

select l.name, x.propid,
sum(x.tot) as finalrent
from landlord l
left join
(select p.landlordid, (p.rent - m.cost) as tot,
p.id as propid 
from property p left join 
maintenance m
on p.id = m.propertyid) as x
on
l.id = x.landlordid
group by l.id, x.propid
;


NAME        PROPID  FINALRENT
J Johnson   1       375
J Johnson   2       480
R Kelly     3       715

25/12/2012


编辑以添加 SQLFIDDLE 以及结果group by landlord only

查询显示扣除成本后的总租金。

询问:

-- group by landlord only

select l.id, l.name,
sum(x.tot) as finalrent, 
sum(COALESCE(x.cost,0)) as TotalCost
from landlord l
left join
(select p.landlordid, 
(p.rent - COALESCE(m.cost,0)) as tot,
p.id as propid, m.cost 
from property p left join 
maintenance m
on p.id = m.propertyid) as x
on l.id = x.landlordid
group by l.id
;

结果:

ID  NAME        FINALRENT   TOTALCOST
1   R Johnson   880         120
2   R Kelly     715         35

27/12/2012

于 2012-12-24T18:23:14.100 回答
0

乔尔的回答非常好。然而,有一种更简单的方式来表达这一点。您可以在属性级别的子查询中进行汇总,然后在外部查询中在房东级别进行汇总:

SELECT l.Id as LandlordId, l.Name, 
       sum(p.rent) as TotalRent,
       coalesce(sum(p.rent), 0) AS TotalRent, 
       coalesce(sum(m.PropertyCost), 0) AS TotalCost
FROM Landlord l left outer join
     Property p
     on l.LandlordId = p.LandlordId left outer join
     (SELECT PropertyId, SUM(Cost) AS PropertyCost
      FROM Maintenance m
      group by PropertyId
     ) m
     on m.PropertyId = p.PropertyId
group by l.LandLordId, l.LandlordName
ORDER BY Landlord.Name

这会在第二个子查询中保存一个连接。

于 2012-12-24T18:20:17.897 回答