如何使用条件逻辑选择要在SQL中加入哪条记录?

时间:2012-10-30 17:22:32

标签: sql join if-statement exists

我正在处理一项查询,除其他事项外,还会根据身份证号码为某人选择一个电话号码。

这段代码得到了它:

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 个答案:

答案 0 :(得分: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]            
    ...

答案 1 :(得分:0)

另一个想法是为子查询中的每种手机类型分配排名,并仅选择第一种。 这可以使用分析函数或suquery(选择count(*)等)来完成,这取决于您的服务器类型。 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

答案 2 :(得分:0)

加入@ Bohemian的建议。如果您在多个查询中经常需要此功能,则可能需要编写表值函数(如果您有db这样的东西)或查看以计算要显示的正确电话号码。然后所有参考电话号码的人都会得到相同的号码。

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

答案 3 :(得分:0)

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

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

CREATE FUNCTION `getPhoneNumber`(_PersonId INT) RETURNS TEXT
BEGIN
    // You SQL query here 
END