我有三张表格如下: 联系人,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
这是一个讨厌的,但我知道会有人会喜欢它:)
答案 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