我正在尝试为一个人获取所有手机,电子邮件和组织,并以平面文件格式显示它。应该有n行,其中n是组织,电子邮件或电话的最大数量。一旦所有值都显示在行中,将显示NULL值,其中NULL是最后的值。电子邮件和电话每人只能有1个PreferredInd。我希望这些行在同一行(其中1个可以为NULL)。我试图在更复杂的查询上执行此操作,但无法使其工作,所以我开始使用这个更简单的示例。
示例表和值:
@ContactPerson
Id Name
1 John Doe
@ContactEmail
Id PersonId Email PreferredInd
1 1 johndoe@us.gov 0
2 1 jdoe@us.gov 1
3 1 johndoe@gmail.com 0
@ContactPhone
Id PersonId Phone PreferredInd
1 1 888-867-5309 0
2 1 305-476-5234 1
@ContactOrganization
Id PersonId Organization
1 1 US Government
2 1 US Army
我希望结果集看起来像:
Name Organization PreferredInd Email Phone
John Doe US Government 1 jdoe@us.gov 888-867-5309
John Doe US Army 0 johndoe@us.gov 305-467-5234
John Doe NULL 0 johndoe@gmail.com NULL
我对此示例的完整SQL代码是here on pastebin.它还包括用于创建示例表的代码。它适用于电子邮件数量超过组织或电话数量的情况,但并非总是如此。我似乎无法弄清楚如何获得我正在寻找的结果。我正在使用的实际表格可以包含每人0或无限的电子邮件,电话或组织。还会有更多的价值观,但我可以自己修复。
您可以帮我修改一下我的查询或向我展示一种更简单的方法吗?如果您有任何疑问,请告诉我,我可以尝试回答。
答案 0 :(得分:4)
这样的事情?
with cte_e as (
select
*,
row_number() over(order by PreferredInd desc, Id) as rn
from ContactEmail
), cte_p as (
select
*,
row_number() over(order by PreferredInd desc, Id) as rn
from ContactPhone
), cte_o as (
select
*,
row_number() over(order by Organization) as rn
from ContactOrganization
), cte_d as (
select distinct rn, PersonId from cte_e union
select distinct rn, PersonId from cte_p union
select distinct rn, PersonId from cte_o
)
select
pr.Name, o.Organization, e.Email, p.Phone
from cte_d as d
left outer join ContactPerson as pr on pr.Id = d.PersonId
left outer join cte_e as e on e.PersonId = d.PersonId and e.rn = d.rn
left outer join cte_p as p on p.PersonId = d.PersonId and p.rn = d.rn
left outer join cte_o as o on o.PersonId = d.PersonId and o.rn = d.rn
<强> sql fiddle demo 强>
它有点笨拙,我可以想到其他几种可能的方法来做到这一点,但我认为这个是最可读的方法
答案 1 :(得分:0)
第1步
编写一个查询,完成所有表的完全连接,最终会为每个人(每个电子邮件或电话号码)提供大量重复行
第2步 编写第二个使用GroupBy对行进行分组的查询,并使用Case或Decode关键字(如c#switch语句)查找首选行值并选择它作为要显示的值