Azure SQL:根据子 select 语句对结果进行分组

Azure SQL: Group a result based on a sub select statement

我有一个查询有问题,我想在其中累积值然后将它们分组 PS: 这是一个简化的例子

CREATE TABLE [dbo].[OWNER](
    [personId] [int] NULL,
    [ownerId] [int] NULL,
    [firstName] [varchar](255) NULL,
    [lastName] [varchar](255) NULL,
)
GO

CREATE TABLE [dbo].[INCOME](
    [personId] [int] NULL,
    [amount] [float] NULL,
    [received] [date] NULL,
)
GO


INSERT INTO OWNER Values(1,null,   'John', 'Smith')
INSERT INTO OWNER Values(1,null,   'John', 'Smith')
INSERT INTO OWNER Values(1,null,   'John', 'Smith')
INSERT INTO OWNER Values(200,1,    'Tom', 'Lawn')
INSERT INTO OWNER Values(3,3,      'Chris', 'Hanson')
INSERT INTO OWNER Values(400,4,    'Jack', 'Man')
INSERT INTO OWNER Values(4,null,   'Donald', 'McMan')
INSERT INTO OWNER Values(5,null,   'John', 'Hanson')
INSERT INTO OWNER Values(700,5,    'Peter', 'Darcy')
INSERT INTO OWNER Values(700,5,    'Peter', 'Darcy')


Insert INTO INCOME VALUES(1, 300, '2020-01-01')
Insert INTO INCOME VALUES(200, 1000, '2020-01-01')
Insert INTO INCOME VALUES(3, 200, '2020-01-01')
Insert INTO INCOME VALUES(4,300, '2020-01-01')
Insert INTO INCOME VALUES(5,300, '2020-01-01')
Insert INTO INCOME VALUES(1,300,  '2020-01-01')
Insert INTO INCOME VALUES(3,300,  '2020-01-01')
Insert INTO INCOME VALUES(5,500,  '2020-01-01')
Insert INTO INCOME VALUES(700,500,  '2020-01-01')

所有者 table 中可以有重复的记录。 要进行汇总,我可以写

select personId, 
       sum(amount) as total,
       count(*) as rows
from income
group by personid

这将导致

personId    total   rows
1           600      2
3           500      2
4           300      1
5           800      2
200         1000     1
700         500      1

问题是我想获取 Owner 的聚合并得到以下结果

personId    total  rows
1           1600   3
3           500    2
4           300    1
5           1300   3

因为 personId 200 的 ownerId 是 1,personId 700 的 ownerId 是 5。 对于如何实现这一目标,我将不胜感激。

您的数据模型确实存在问题 -- 您应该解决这个问题。在 owner 中有重复的行是很糟糕的。至少,你可以有一个生效日期,这样你就知道最近的记录是什么

也就是说,您可以使用 apply 选择任意匹配记录并使用:

select coalesce(o.ownerid, i.personid), 
       sum(amount) as total,
       count(*) as rows
from income i cross apply
     (select top (1) o.*
      from owner o
      where o.personid = i.personid
     ) o
group by coalesce(o.ownerid, i.personid);

Here 是一个 db<>fiddle.