SQL 根据类型字段加入两个实体
SQL join two entities depending on type field
在我使用 MSSQL Server 2016 的 Microsoft Dynamics CRM 2016(本地)中,我尝试创建一个报告(使用 ReportServer),它提供所有开放机会的最新活动:
我想找到机会 (FilteredOpportunity) 最近的 activity(即 FilteredActivityPointer)。这个问题的第一个(也是简单的)解决方案(使用 MSSQL 的高性能查询)是这样提供的:
现在我需要像下面这样扩展场景(遍历从 activity 到机会的 2 条备选路径):
FilteredActivityPointer 包含一个名为 referenceobjecttypecode 的字段:该字段包含:
* 1 用于与活动相关的活动,在这种情况下,字段 referenceobjectid 包含帐户的 id
* 2 对于与联系人相关的活动,在这种情况下,字段 referenceobjectid 包含联系人的 ID
如何扩展以下查询...
SELECT opp.opportunityid, opp.name as OpportunityName, opp.statecode, opp.statecodename, fac.accountid, fac.name As AccountName, fa.regardingobjecttypecode, fa.activitytypecodename, fa.owneridname, fa.actualend As DateCompleted, fa.description As ActivityDescription
FROM FilteredAccount fac cross apply
(SELECT TOP 1 *
FROM FilteredActivityPointer fa
WHERE fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.regardingobjecttypecode=1
order by fa.actualend desc
) fa
JOIN FilteredOpportunity as opp
ON fac.accountid = opp.accountid
WHERE opp.statecode = 0
... 这样我就可以通过加入帐户和加入 opps 或 通过加入联系人、加入帐户加入帐户来获得最新的 FilteredActivityPointer。
我不知道如何才能做到这一点
我这样试过,但我迷路了:
SELECT opp.opportunityid, opp.name as OpportunityName, opp.statecode, opp.statecodename, fac.accountid, fac.name As AccountName, fa.regardingobjecttypecode, fa.activitytypecodename, fa.owneridname, fa.actualend As DateCompleted, fa.description As ActivityDescription
FROM FilteredAccount fac cross apply
(SELECT TOP 1 *
FROM FilteredActivityPointer fa
WHERE fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.regardingobjecttypecode=1
order by fa.actualend desc
) fa
FilteredAccount fac2 cross apply
(SELECT TOP 1 *
FROM FilteredActivityPointer fa2
join FilteredContact as co
ON fa2.regardingobjectid = co.contactid and fa2.regardingobjecttypecode = 2
join FilteredAccount as ac
on ac.accountid = opp.account.id;
WHERE fa.statecode = 1
order by fa.actualend desc
) fa2
JOIN FilteredOpportunity as opp
ON fac.accountid = opp.accountid
WHERE opp.statecode = 0
我试图在我的 MicrosoftDynamics CRM 2016 中找到所有开放机会 (FilteredOpportunity) 的最新 activity (FilteredActivity)。听起来很简单实际上相当复杂,因为活动可能与联系人或直接相关机会。所以这个问题归结为我如何组合两个结果集的问题,然后 select 最近的 activity 出两个结果集的组合:
* 每个机会提供最新的 activity
* 为每个帐户(每个联系人)
提供最新的 activity
这需要工会。为了理解整个问题,我在下图中可视化了关系。:
对于结果集 1 Gordon Linoff and delivery this very efficient :
对于结果集 2 GMB delivered a very clever :
两个结果都是有效的并且非常高效。两个结果集都可以设计为提供相同的结构:与机会相关的活动。
因此,对于结果集 1,我准备了以下查询:
select fac.name as accountname, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, fac.accountid, opp.opportunityid, opp.name as opportunityname
from FilteredAccount fac cross apply
(select top (1) fa.*
from FilteredActivityPointer fa
where fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.activitytypecode != 10004
order by fa.actualend desc
) fa
Join FilteredOpportunity opp on opp.accountid = fac.accountid and opp.statecode = 0
对于结果集 2,我准备了以下查询:
select t.name as accountname, t.actualend, t.description, t.activitytypecodename, t.activitytypecode, t.accountid, t.opportunityid, t.opportunityname
from (
select ac.accountid, opp.name as opportunityname, opp.opportunityid, ac.name, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, row_number() over(partition by ac.accountid order by fa.actualend desc) rn
from FilteredContact co
inner join FilteredActivityPointer fa
on fa.regardingobjectid = co.contactid
and fa.regardingobjecttypecode = 2
and fa.activitytypecode != 10004
inner join FilteredAccount ac
on ac.accountid = co.accountid
inner join FilteredOpportunity opp
on opp.accountid = ac.accountid
and opp.statecode = 0
) t
where rn = 1
我尝试用相同的列名排列结果集。
现在我使用 union 合并两个结果集:
select allactivities.accountname as accountname, allactivities.actualend, allactivities.description, allactivities.activitytypecodename, allactivities.activitytypecode, allactivities.accountid, allactivities.opportunityid, allactivities.opportunityname
from
(
(select fac.name as accountname, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, fac.accountid, opp.opportunityid, opp.name as opportunityname
from FilteredAccount fac cross apply
(select top (1) fa.*
from FilteredActivityPointer fa
where fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.activitytypecode != 10004
order by fa.actualend desc
) fa
Join FilteredOpportunity opp on opp.accountid = fac.accountid and opp.statecode = 0
)
Union
(select t.name as accountname, t.actualend, t.description, t.activitytypecodename, t.activitytypecode, t.accountid, t.opportunityid, t.opportunityname
from
(
select ac.accountid, opp.name as opportunityname, opp.opportunityid, ac.name, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, row_number() over(partition by ac.accountid order by fa.actualend desc) rn
from FilteredContact co
inner join FilteredActivityPointer fa
on fa.regardingobjectid = co.contactid
and fa.regardingobjecttypecode = 2
and fa.activitytypecode != 10004
inner join FilteredAccount ac
on ac.accountid = co.accountid
inner join FilteredOpportunity opp
on opp.accountid = ac.accountid
and opp.statecode = 0
) t
where rn = 1
)
) allactivities
到目前为止,结果似乎还不错。
现在我第二次使用了 "over (partition)" 方法,结果是:
select activity.accountname, activity.actualend, activity.description, activity.activitytypecodename, activity.activitytypecode, activity.accountid, activity.opportunityid, activity.opportunityname
from
(
select allactivities.accountname as accountname, allactivities.actualend, allactivities.description, allactivities.activitytypecodename, allactivities.activitytypecode, allactivities.accountid, allactivities.opportunityid, allactivities.opportunityname, row_number() over(partition by allactivities.accountid order by allactivities.actualend desc) row_nr
from
(
(select fac.name as accountname, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, fac.accountid, opp.opportunityid, opp.name as opportunityname
from FilteredAccount fac cross apply
(select top (1) fa.*
from FilteredActivityPointer fa
where fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.activitytypecode != 10004
order by fa.actualend desc
) fa
Join FilteredOpportunity opp on opp.accountid = fac.accountid and opp.statecode = 0
)
Union
(select t.name as accountname, t.actualend, t.description, t.activitytypecodename, t.activitytypecode, t.accountid, t.opportunityid, t.opportunityname
from
(
select ac.accountid, opp.name as opportunityname, opp.opportunityid, ac.name, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, row_number() over(partition by ac.accountid order by fa.actualend desc) rn
from FilteredContact co
inner join FilteredActivityPointer fa
on fa.regardingobjectid = co.contactid
and fa.regardingobjecttypecode = 2
and fa.activitytypecode != 10004
inner join FilteredAccount ac
on ac.accountid = co.accountid
inner join FilteredOpportunity opp
on opp.accountid = ac.accountid
and opp.statecode = 0
) t
where rn = 1
)
) allactivities
) activity
where row_nr = 1
瞧!
请考虑到我在解决方案中添加了 "union"。 Gordon Linoff and GMB 提供了上述问题的真正解决方案。没有那些才华横溢的 SQL 大师的帮助,我做不到!
在我使用 MSSQL Server 2016 的 Microsoft Dynamics CRM 2016(本地)中,我尝试创建一个报告(使用 ReportServer),它提供所有开放机会的最新活动:
我想找到机会 (FilteredOpportunity) 最近的 activity(即 FilteredActivityPointer)。这个问题的第一个(也是简单的)解决方案(使用 MSSQL 的高性能查询)是这样提供的:
现在我需要像下面这样扩展场景(遍历从 activity 到机会的 2 条备选路径):
FilteredActivityPointer 包含一个名为 referenceobjecttypecode 的字段:该字段包含: * 1 用于与活动相关的活动,在这种情况下,字段 referenceobjectid 包含帐户的 id * 2 对于与联系人相关的活动,在这种情况下,字段 referenceobjectid 包含联系人的 ID
如何扩展以下查询...
SELECT opp.opportunityid, opp.name as OpportunityName, opp.statecode, opp.statecodename, fac.accountid, fac.name As AccountName, fa.regardingobjecttypecode, fa.activitytypecodename, fa.owneridname, fa.actualend As DateCompleted, fa.description As ActivityDescription
FROM FilteredAccount fac cross apply
(SELECT TOP 1 *
FROM FilteredActivityPointer fa
WHERE fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.regardingobjecttypecode=1
order by fa.actualend desc
) fa
JOIN FilteredOpportunity as opp
ON fac.accountid = opp.accountid
WHERE opp.statecode = 0
... 这样我就可以通过加入帐户和加入 opps 或 通过加入联系人、加入帐户加入帐户来获得最新的 FilteredActivityPointer。
我不知道如何才能做到这一点 我这样试过,但我迷路了:
SELECT opp.opportunityid, opp.name as OpportunityName, opp.statecode, opp.statecodename, fac.accountid, fac.name As AccountName, fa.regardingobjecttypecode, fa.activitytypecodename, fa.owneridname, fa.actualend As DateCompleted, fa.description As ActivityDescription
FROM FilteredAccount fac cross apply
(SELECT TOP 1 *
FROM FilteredActivityPointer fa
WHERE fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.regardingobjecttypecode=1
order by fa.actualend desc
) fa
FilteredAccount fac2 cross apply
(SELECT TOP 1 *
FROM FilteredActivityPointer fa2
join FilteredContact as co
ON fa2.regardingobjectid = co.contactid and fa2.regardingobjecttypecode = 2
join FilteredAccount as ac
on ac.accountid = opp.account.id;
WHERE fa.statecode = 1
order by fa.actualend desc
) fa2
JOIN FilteredOpportunity as opp
ON fac.accountid = opp.accountid
WHERE opp.statecode = 0
我试图在我的 MicrosoftDynamics CRM 2016 中找到所有开放机会 (FilteredOpportunity) 的最新 activity (FilteredActivity)。听起来很简单实际上相当复杂,因为活动可能与联系人或直接相关机会。所以这个问题归结为我如何组合两个结果集的问题,然后 select 最近的 activity 出两个结果集的组合: * 每个机会提供最新的 activity * 为每个帐户(每个联系人)
提供最新的 activity这需要工会。为了理解整个问题,我在下图中可视化了关系。:
对于结果集 1 Gordon Linoff and delivery this very efficient
两个结果都是有效的并且非常高效。两个结果集都可以设计为提供相同的结构:与机会相关的活动。
因此,对于结果集 1,我准备了以下查询:
select fac.name as accountname, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, fac.accountid, opp.opportunityid, opp.name as opportunityname
from FilteredAccount fac cross apply
(select top (1) fa.*
from FilteredActivityPointer fa
where fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.activitytypecode != 10004
order by fa.actualend desc
) fa
Join FilteredOpportunity opp on opp.accountid = fac.accountid and opp.statecode = 0
对于结果集 2,我准备了以下查询:
select t.name as accountname, t.actualend, t.description, t.activitytypecodename, t.activitytypecode, t.accountid, t.opportunityid, t.opportunityname
from (
select ac.accountid, opp.name as opportunityname, opp.opportunityid, ac.name, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, row_number() over(partition by ac.accountid order by fa.actualend desc) rn
from FilteredContact co
inner join FilteredActivityPointer fa
on fa.regardingobjectid = co.contactid
and fa.regardingobjecttypecode = 2
and fa.activitytypecode != 10004
inner join FilteredAccount ac
on ac.accountid = co.accountid
inner join FilteredOpportunity opp
on opp.accountid = ac.accountid
and opp.statecode = 0
) t
where rn = 1
我尝试用相同的列名排列结果集。
现在我使用 union 合并两个结果集:
select allactivities.accountname as accountname, allactivities.actualend, allactivities.description, allactivities.activitytypecodename, allactivities.activitytypecode, allactivities.accountid, allactivities.opportunityid, allactivities.opportunityname
from
(
(select fac.name as accountname, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, fac.accountid, opp.opportunityid, opp.name as opportunityname
from FilteredAccount fac cross apply
(select top (1) fa.*
from FilteredActivityPointer fa
where fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.activitytypecode != 10004
order by fa.actualend desc
) fa
Join FilteredOpportunity opp on opp.accountid = fac.accountid and opp.statecode = 0
)
Union
(select t.name as accountname, t.actualend, t.description, t.activitytypecodename, t.activitytypecode, t.accountid, t.opportunityid, t.opportunityname
from
(
select ac.accountid, opp.name as opportunityname, opp.opportunityid, ac.name, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, row_number() over(partition by ac.accountid order by fa.actualend desc) rn
from FilteredContact co
inner join FilteredActivityPointer fa
on fa.regardingobjectid = co.contactid
and fa.regardingobjecttypecode = 2
and fa.activitytypecode != 10004
inner join FilteredAccount ac
on ac.accountid = co.accountid
inner join FilteredOpportunity opp
on opp.accountid = ac.accountid
and opp.statecode = 0
) t
where rn = 1
)
) allactivities
到目前为止,结果似乎还不错。
现在我第二次使用了 "over (partition)" 方法,结果是:
select activity.accountname, activity.actualend, activity.description, activity.activitytypecodename, activity.activitytypecode, activity.accountid, activity.opportunityid, activity.opportunityname
from
(
select allactivities.accountname as accountname, allactivities.actualend, allactivities.description, allactivities.activitytypecodename, allactivities.activitytypecode, allactivities.accountid, allactivities.opportunityid, allactivities.opportunityname, row_number() over(partition by allactivities.accountid order by allactivities.actualend desc) row_nr
from
(
(select fac.name as accountname, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, fac.accountid, opp.opportunityid, opp.name as opportunityname
from FilteredAccount fac cross apply
(select top (1) fa.*
from FilteredActivityPointer fa
where fa.regardingobjectid = fac.accountid and fa.statecode = 1 and fa.activitytypecode != 10004
order by fa.actualend desc
) fa
Join FilteredOpportunity opp on opp.accountid = fac.accountid and opp.statecode = 0
)
Union
(select t.name as accountname, t.actualend, t.description, t.activitytypecodename, t.activitytypecode, t.accountid, t.opportunityid, t.opportunityname
from
(
select ac.accountid, opp.name as opportunityname, opp.opportunityid, ac.name, fa.actualend, fa.description, fa.activitytypecodename, fa.activitytypecode, row_number() over(partition by ac.accountid order by fa.actualend desc) rn
from FilteredContact co
inner join FilteredActivityPointer fa
on fa.regardingobjectid = co.contactid
and fa.regardingobjecttypecode = 2
and fa.activitytypecode != 10004
inner join FilteredAccount ac
on ac.accountid = co.accountid
inner join FilteredOpportunity opp
on opp.accountid = ac.accountid
and opp.statecode = 0
) t
where rn = 1
)
) allactivities
) activity
where row_nr = 1
瞧!
请考虑到我在解决方案中添加了 "union"。 Gordon Linoff and GMB 提供了上述问题的真正解决方案。没有那些才华横溢的 SQL 大师的帮助,我做不到!