1

次の3つのテーブルがあります:Contact、Custom_Field、Custom_Field_Value。

各連絡先は、Custom_Fieldごとに1つのCustom_Field_Valueレコードを持つことができます。したがって、ContactとCustom_Field_Valueの間には1:多くの関係がありますが、それほど単純ではありません。

特定のCustom_Fieldが設定されていない連絡先を選択する必要がある(つまり、ContactとCustom_Fieldにリンクする対応するCustom_Field_Valueレコードが存在しない)1つのエッジケースを除いて、すべてが正常に機能します。これは驚くほど難しいです。通常の「左結合してNULLを探す」アプローチを使用することはできません。これは、カスタムフィールドが異なる可能性があるためですが、探しているものではありません。「WhereCustom_Field_ID=10」と言う必要がありますが、探しているものが存在しないため、言えません。

私の考え方はこの方向に向かっていましたが、今は結び目で結ばれています。

Select ID, First_Name, Last_Name, CF_ID  From 

(

(Select Contact.ID, First_Name, Last_Name, Custom_Field_Value.ID as CFV_ID, Custom_Field_Value.CustomFieldID as CF_ID, TextValue 
From Contact Inner Join Custom_Field_Value on Contact.ID = Custom_Field_Value.ContactID 
Where Custom_Field_Value.CustomFieldID=23 Order By Contact.ID)

UNION

(Select Contact.ID, First_Name, Last_Name, Custom_Field_Value.ID as CFV_ID, Custom_Field_Value.CustomFieldID as CF_ID, TextValue 
From Contact LEFT Join Custom_Field_Value on Contact.ID = Custom_Field_Value.ContactID 
Order by Contact.ID)

) as A


Group BY `ID`, CF_ID ASC

何百万ものレコードが存在する可能性があり、誰かがカスタムフィールドを追加するたびに、データベースは何百万もの対応する空白のレコードを挿入する必要があるため、すべての可能性に対して空白のレコードを作成したくありません。

私たちがこれを行うことができれば本当に素晴らしいでしょう:

Select ID From thingy 
EXCLUDE
Select * From thingy Where x = true

これは厄介なものですが、それを気に入る人がそこにいることを私は知っています:)

4

2 に答える 2

1

さて、私は今よりよく理解していると思います。私はサブクエリなしでそれをやってのけることを試みていました、しかし私は私ができるかどうかわかりません。

やってみませんか

Select Contact.ID, First_Name, Last_Name, Custom_Field_Value.ID as CFV_ID, Custom_Field_Value.CustomFieldID as CF_ID, TextValue 
From Contact LEFT Join Custom_Field_Value on Contact.ID = Custom_Field_Value.ContactID 
WHERE NOT EXISTS(SELECT * FROM Custom_Field_Value cfv2 WHERE cfv2.ContactID = Contact.ID AND cfv2.CustomFieldID=23)
Order by Contact.ID

NOT EXISTSサブクエリは、連絡先にそのフィールドの値がない行のみを返す必要があります。

于 2013-02-14T16:58:09.540 に答える
0

これは私が最終的に作成したクレイジーなSQLであり、ユーザーによって動的に作成されます。誰かが使用する場合に備えて公開するだけです。(最適化に関するヒントは大歓迎です!):

問題は、欠落している動的レコードを選択する必要があるだけでなく、左結合クエリを1つの結果に結合する必要があることです。

SELECT * FROM (
    (SELECT * FROM Contact 
        WHERE (...some dynamic stuff...) 
    ) 
    UNION All 
   (SELECT Contact.* FROM Contact Inner Join Contact_Campaign_Link ON Contact.ID=Contact_Campaign_Link.Contact_ID 
       WHERE ((Campaign_ID=31))
   ) 
UNION All 
    (SELECT * FROM Contact 
        WHERE (CustomerID=3) 
        AND (NOT EXISTS 
            (SELECT * FROM Custom_Field_Value cfv2 
                WHERE (cfv2.ContactID = Contact.ID) 
                AND (cfv2.CustomFieldID =27) )) ORDER BY Contact.ID)
            ) As tbl 

GROUP BY tbl.ID HAVING COUNT(*)=3 Order by ID
于 2013-02-19T14:44:10.867 に答える