在mySQL中选择不匹配的字段

时间:2013-02-14 16:47:55

标签: mysql

我有三张表格如下: 联系人,Custom_Field,Custom_Field_Value。

每个联系人可以为每个Custom_Field都有一个Custom_Field_Value记录。所以Contact和Custom_Field_Value之间存在1:很多关系,但它并不那么简单。

一切正常 - 除了一个边缘情况,我需要选择没有设置特定Custom_Field的联系人(即没有相应的Custom_Field_Value记录链接到Contact和Custom_Field)。这非常困难。我不能只使用正常的“左连接并寻找NULL”方法,因为它们可能有不同的自定义字段 - 但不是我正在寻找的那个。我需要说“Where 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

这是一个讨厌的,但我知道会有人会喜欢它:)

2 个答案:

答案 0 :(得分: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子查询应仅返回联系人没有该字段值的行。

答案 1 :(得分: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