1

私は、とりわけ、ID番号を指定された人の1つの電話番号を選択するクエリに取り組んでいます。

このコードのビットはそれを取得します:

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

そのため、「携帯電話」よりも「自宅の電話」を優先し、説明のないものよりも「携帯電話」を優先します。でも、参加の途中でどうやってやるのかわからない。3つの別々の選択を書かなくてもそれを行う方法はありますか?この結合が含まれているクエリは醜くて大規模で、多数の結合があるため、分離するのは困難です。助言がありますか?

4

4 に答える 4

3

3 つの電話番号が異なる行にあるため、3 つの結合が必要です。ステートメントを使用して、casenull でない最初のものを選択します。

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

もう 1 つのアイデアは、サブクエリで各電話タイプにランクを割り当て、最初のものだけを選択することです。これは、分析関数または suquery (select 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
于 2012-10-30T18:09:55.963 に答える
0

@Bohemianの提案に追加します。この機能が複数のクエリで頻繁に必要になる場合は、テーブル値関数 (データベースにそのようなものがある場合) を作成するか、表示する正しい電話番号を計算するビューを使用することをお勧めします。次に、電話番号へのすべての参照は常に同じ番号を取得します。

別の方法としては、1 つだけの電話番号をフラグ フィールド (contactphone と呼びます) でメインの電話番号としてマークし、トリガーを通じてこれを更新し続けることです。これは、連絡を受ける人が、どちらを通じて連絡を取りたいかを指定できる場合に便利です。

于 2012-10-30T18:14:29.307 に答える
0

ストアド関数を作成する権限があると仮定すると、クエリのその部分を関数呼び出しに置き換えます。返す電話番号を決定するロジックは、この関数に記述できます。これにより、メインのクエリがクリーンに保たれ、関数は他のクエリでも再利用できます。

MySQL 関数スタブは次のようになります。

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