我有3张桌子。一个是服务表。每个服务都可以有一些选项,这些选项位于选项表中。第三个表是链接到每个选项的联系人列表。
所以,表格如下:
服务
serviceID
100
101
选项
optionID serviceID price
1 100 10.5
2 100 100
3 101 25.25
4 101 67.90
contactOptions
contactID optionID serviceID priceOverride
10 1 100 NULL
10 2 100 NULL
10 3 101 30
10 4 101 100
11 1 100 12
11 3 101 NULL
12 2 100 55
12 3 101 NULL
12 4 101 NULL
13 1 100 NULL
13 2 100 66
13 4 101 NULL
如您所见,contactID 10有4个与他相关联的选项。 11只有2只与她联系,而12只和13只都只有3只。
我正在尝试找到一种方法来获取没有所有4个选项的contactID,以及它们缺少哪些选项。
我试过(SQL Fiddle:http://sqlfiddle.com/#!2/ca937/7):
SELECT *
FROM contactOptions
LEFT JOIN options
ON options.optionID = contactOptions.optionID
AND options.serviceID = contactOptions.serviceID
但是这只返回了我所有的12行,我想要相反的,不存在的行。
如何退回没有全部4个选项的联系人以及他们没有的选项?
返回的行应为:
contactID optionID serviceID
11 2 100
11 4 101
12 1 100
13 3 101
我最终想知道哪些服务(以及哪些选项)没有与之关联的联系人。
编辑:我越来越近了,这就是我现在所拥有的
SELECT contactID,
contactOptions.serviceID,contactOptions.optionID AS x,
options.optionID AS y
FROM contactOptions
JOIN options
ON options.serviceID = contactOptions.serviceID
HAVING x != y
这是我当前的SQL小提琴:http://sqlfiddle.com/#!2/ca937/35
返回:
CONTACTID SERVICEID X Y
10 100 1 2
10 100 2 1
10 101 3 4
10 101 4 3
11 100 1 2
11 101 3 4
12 100 2 1
12 101 3 4
12 101 4 3
13 100 1 2
13 100 2 1
13 101 4 3
这包含我想要的行,但它也包含我不想要的行。从这个结果我基本上需要删除联系人具有相同X和Y值的所有行,然后剩下的行是正确的。
编辑2 :我现在更近了(http://sqlfiddle.com/#!2/ca937/53):
SELECT contactID,
contactOptions.serviceID,contactOptions.optionID AS x,
options.optionID AS y
FROM contactOptions
JOIN options
ON options.serviceID = contactOptions.serviceID
GROUP BY contactID,serviceID
HAVING x != y
这给了我:
CONTACTID SERVICEID X Y
12 100 2 1
13 101 4 3
现在我有2个我想要的行。我只需要弄清楚如何获取11行。
答案 0 :(得分:2)
SELECT contacts_options_full.contactID, contacts_options_full.optionID, options.serviceID
FROM
(
SELECT contactID, optionID
FROM (SELECT optionID FROM options) o
CROSS JOIN
(SELECT DISTINCT contactID FROM contactOptions) co
) contacts_options_full
LEFT JOIN contactOptions ON contacts_options_full.contactID = contactOptions.contactID
AND contactOptions.optionID = contacts_options_full.optionID
JOIN options ON contacts_options_full.optionID = options.optionID
WHERE contactOptions.serviceID IS NULL
ORDER BY contacts_options_full.contactID, contacts_options_full.optionID
on sqlfiddle
答案 1 :(得分:1)
SELECT *,COUNT(contactID)as cc
FROM contactOptions
GROUP BY contactID
HAVING cc < 4
当然要计算所有选项:
SELECT COUNT(*) FROM options
在您拥有以前查询的所有联系人ID之后,您可以为每个联系人ID运行此查询:
SELECT optionID FROM options WHERE optionID NOT IN (SELECT optionID FROM contactOptions WHERE contactID = 11)
答案 2 :(得分:1)
我正在研究这个问题,我想出了自己的答案。
SELECT serviceContact.contactID, options.optionID,
serviceContact.serviceID
FROM options
JOIN(
SELECT DISTINCT contactID, services.serviceID, GROUP_CONCAT(optionID) as options
FROM contactOptions
JOIN services ON services.serviceID = contactOptions.serviceID
GROUP BY contactID, services.serviceID
) serviceContact ON serviceContact.serviceID = options.serviceID
WHERE NOT FIND_IN_SET(optionID,serviceContact.options)
这里的诀窍是GROUP_CONCAT
与NOT FIND_IN_SET
混合在一起。这让我可以在链接表中获得 not 选项。