1

我有如下三个表:Contact、Custom_Field、Custom_Field_Value。

每个联系人可以为每个 Custom_Field 拥有一个 Custom_Field_Value 记录。因此,Contact 和 Custom_Field_Value 之间存在 1:many 关系,但并不是那么简单。

一切正常 - 除了一种边缘情况,我需要选择未设置特定 Custom_Field 的联系人(即不存在链接到联系人和 Custom_Field 的相应 Custom_Field_Value 记录)。这出乎意料地困难。我不能只使用普通的“左连接并查找 NULL”方法,因为它们可能有不同的自定义字段——但不是我要找的那个。我需要说“Custom_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 - 由用户动态创建。只是发布它以防它对任何人有用。(非常欢迎任何关于优化的提示!):

问题是我不仅必须选择丢失的动态记录,而且还必须将左连接查询连接到一个结果中。

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 回答