1

我正在处理一个查询,除其他事项外,为一个给定 ID 号码的人选择一个电话号码。

这段代码得到了它:

LEFT JOIN [thedatabasename].dbo.[thetablename] Phone 
ON p.PersonId = phone.PersonId 
AND (phone.[Description] = 'Home Phone' 
     OR phone.[Description] = 'Cell Phone' 
     OR phone.[Description] is null)

这行得通,但我想要的是它做一些在概念上更像

IF EXISTS select [phone number] from <tablename> where description = 'Home phone'
ELSE IF EXISTS select [phone number] from <tablename> where description = 'cell phone'
ELSE IF EXISTS select [phone number] from <tablename> where description is null

因此它更喜欢“家庭电话”而不是“手机”,并且更喜欢“手机”而不是没有描述的手机。我不知道如何在我加入的过程中做到这一点。有没有办法做到这一点而不必编写三个单独的选择?此连接所属的查询丑陋且庞大,并且有一堆连接,因此将其分离出来会很困难。有什么建议么?

4

4 回答 4

3

因为这三个电话号码位于不同的行中,所以您需要三个联接。使用case语句选择第一个不为空的:

select
    ...
    case 
        when phone1.[phone number] is not null then phone1.[phone number]
        when phone2.[phone number] is not null then phone2.[phone number]
        else phone3.[phone number] 
    end as [phone number]            
    ...
LEFT JOIN [thedatabasename].dbo.[thetablename] phone1
    ON p.PersonId = phone1.PersonId AND phone1.[Description] = 'Home Phone'
LEFT JOIN [thedatabasename].dbo.[thetablename] phone2
    ON p.PersonId = phone2.PersonId AND phone2.[Description] = 'Cell Phone'
LEFT JOIN [thedatabasename].dbo.[thetablename] phone3
    ON p.PersonId = phone3.PersonId AND phone3.[Description] is null

请注意赋予连接Phone行的不同别名以区分它们。


如果您的数据库支持COALESCE(或类似),您可以将您的选择简化为:

select
    ...
    coalesce (phone1.[phone number], phone2.[phone number], phone3.[phone number]) as [phone number]            
    ...
于 2012-10-30T17:45:58.650 回答
0

假设您有权创建存储函数,我将用函数调用替换查询的那部分。决定返回哪个电话号码的逻辑可以写在这个函数中。这使主查询保持干净,并且该函数也可以在其他查​​询中重用。

MySQL 函数存根看起来像这样:

CREATE FUNCTION `getPhoneNumber`(_PersonId INT) RETURNS TEXT
BEGIN
    // You SQL query here 
END
于 2012-10-30T23:40:39.280 回答
0

另一个想法是为子查询中的每种电话类型分配一个排名,并只选择第一个。这可以通过分析函数或 suquery (select count(*) etc) 来完成,这取决于您的服务器类型。mysql 不支持分析函数,它可能看起来有点奇怪,但应该可以工作:-)。使用 MSSQL,它提供:

select * 
from (
    select rank() over ( 
            partition by Person.PersonId
            order by 
                case when Phone.PhoneDescription = 'Home' then 1
                when Phone.PhoneDescription = 'Cell' then 2
                else 3 end  ) as [rank],
        Person.name, Phone.PhoneDescription, Phone.PhoneNumber
    from Person
    left join Phone on Person.PersonId = Phone.PersonId
) PhoneNumbers
where [rank] = 1
于 2012-10-30T18:09:55.963 回答
0

补充@Bohemian的建议。如果您在多个查询中经常需要此功能,您可能需要编写一个表值函数(如果您的数据库有这样的东西)或查看来计算要显示的正确电话号码。然后所有对电话号码的引用将始终获得相同的号码。

另一种方法是使用标志字段(称为联系电话)将一个且唯一的电话号码标记为主要电话号码,并通过触发器保持更新。如果要联系的人可以指定他希望通过哪一个联系,这将很有用。

于 2012-10-30T18:14:29.307 回答