postgresql:根据最新的透视行进行选择
给出一个简单的模式:postgresql:根据最新的透视行进行选择,postgresql,Postgresql,给出一个简单的模式: users ----- - id<int> - name<string> organisations ------------- - id<int> - name<string> organisations_users ------------------- - id<int> - userId<int> - organisationId<int> - joinedAt<date&
users
-----
- id<int>
- name<string>
organisations
-------------
- id<int>
- name<string>
organisations_users
-------------------
- id<int>
- userId<int>
- organisationId<int>
- joinedAt<date>
此时,用户[1,3]在组织2中,用户2在组织3中。没有人在组织1中
预期结果
如果我试图让组织2中的每个人都参与进来,我将获得用户1和3(以及他们的联合日期
日期):
我不会得到用户2,因为尽管该用户最初在组织2中,但该用户随后加入了组织3。这应该可以做到:
select u.id, u.name, ou.organisationId, ou.joinedat
from users u
join (
select userid, organisationid, joinedat,
max(joinedat) over (partition by userid) as last_join
from organisations_users
) ou on u.id = ou.userid and ou.joinedat = ou.last_join
where ou.organisationid = 2;
这假设一个用户不能同时在两个组织中。因此,最新的joinedat值标识用户的当前组织
如果用户可以同时加入多个组织,则需要将max(joinedat)over(按用户ID划分)
更改为max(joinedat)over(按用户ID划分,按组织ID划分)
另一个选项是使用
distinct on()
而不是窗口函数。通常,distinct on()
解决方案的性能更好:
select u.id, u.name, ou.organisationId, ou.joinedat
from users u
join (
select distinct on (userid) userid, organisationid, joinedat
from organisations_users
order by userid, joinedat desc
) ou on u.id = ou.userid
where ou.organisationid = 2
这应该做到:
select u.id, u.name, ou.organisationId, ou.joinedat
from users u
join (
select userid, organisationid, joinedat,
max(joinedat) over (partition by userid) as last_join
from organisations_users
) ou on u.id = ou.userid and ou.joinedat = ou.last_join
where ou.organisationid = 2;
这假设一个用户不能同时在两个组织中。因此,最新的joinedat值标识用户的当前组织
如果用户可以同时加入多个组织,则需要将max(joinedat)over(按用户ID划分)
更改为max(joinedat)over(按用户ID划分,按组织ID划分)
另一个选项是使用
distinct on()
而不是窗口函数。通常,distinct on()
解决方案的性能更好:
select u.id, u.name, ou.organisationId, ou.joinedat
from users u
join (
select distinct on (userid) userid, organisationid, joinedat
from organisations_users
order by userid, joinedat desc
) ou on u.id = ou.userid
where ou.organisationid = 2
备选方案,避免使用窗口函数和max()
选择u.id、u.name
,ou.organizationid
,ou.joinedAt
来自用户u
加入组织(用户)
ON u.id=ou.userId
和ou.joinedAt备选方案,避免使用窗口函数和max()
选择u.id、u.name
,ou.organizationid
,ou.joinedAt
来自用户u
加入组织(用户)
ON u.id=ou.userId
和ou.joined回答您的问题,并添加一些示例数据和基于该数据的预期输出。文本请,因为在组织用户
表中有一个加入的
列,但没有一个退出的
列,所以每个曾经出现在组织X
中的用户仍然会出现。@a_horse\u没有名字:就可以了now@wildplasser:没有,新机构取代旧机构ones@a_horse_with_no_name:使用样本数据和预期结果编辑。您的问题,并添加一些样本数据和基于该数据的预期输出。文本请,因为在组织用户
表中有一个加入的
列,但没有一个退出的
列,所以每个曾经出现在组织X
中的用户仍然会出现。@a_horse\u没有名字:就可以了now@wildplasser:没有,新机构取代旧机构ones@a_horse_with_no_name:使用样本数据和预期结果编辑。
SELECT u.id, u.name
, ou.organisationId
, ou.joinedAt
FROM users u
JOIN organisations_users ou
ON u.id = ou.userId
AND ou.joinedAt <= now()
AND NOT EXISTS ( -- suppress all but the latest
SELECT * FROM organisations_users nx
WHERE nx.userId = ou.userId
AND nx.organisationId <> ou.organisationId
AND nx.joinedAt <= now()
AND nx.joinedAt > ou.joinedAt
)
WHERE ou.organisationId = 2
;