3

我正在尝试获取一个人的所有电话、电子邮件和组织,并以平面文件格式显示。应该有 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 代码位于 pastebin 上。它还包括用于创建示例表的代码。当电子邮件的数量超过组织或电话的数量时,它会起作用,但这并不总是正确的。我似乎无法弄清楚如何获得我正在寻找的结果。我正在使用的实际表格每人可以有 0 个或无限个电子邮件、电话或组织。还会有更多的值,但我可以自己解决。

你能帮我解决我的查询或告诉我一个更简单的方法吗?如果您有任何问题,请告诉我,我可以尝试回答。

4

2 回答 2

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

这有点笨拙,我可以想到其他几种可能的方法来做到这一点,但我认为这是最易读的一种

于 2013-10-02T19:20:48.897 回答
0

步骤1

编写一个对所有表进行完全连接的查询,最终每个人(每个电子邮件或电话号码)都会有很多重复的行

步骤 2 编写第二个查询,使用 GroupBy 对行进行分组,并使用 Case 或 Decode 关键字(如 ac# switch 语句)查找首选行值并将其选择为要显示的值

于 2013-10-02T19:14:54.660 回答