4

我有 3 张桌子。一个是服务表。每个服务都可以有一些选项,这些选项在选项表中。第三个表是链接到每个选项的联系人列表。

因此,表格如下所示:

服务

serviceID
   100
   101

选项

optionID    serviceID    price
    1         100        10.5
    2         100        100
    3         101        25.25
    4         101        67.90

联系人选项

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 个选项的联系人 ID,以及他们缺少哪些选项。

我试过(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 Fiddle: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 的行。

4

3 回答 3

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

sqlfiddle上

于 2012-10-25T22:07:31.843 回答
1
SELECT *,COUNT(contactID)as cc
FROM contactOptions
GROUP BY contactID
HAVING cc < 4

当然要计算所有选项,只需执行以下操作:

SELECT COUNT(*) FROM options

编辑评论:

在您拥有之前查询的所有contactID 之后,您可以为每个contactID 运行此查询:

SELECT optionID FROM options WHERE optionID NOT IN (SELECT optionID FROM contactOptions WHERE contactID = 11)
于 2012-10-25T21:30:56.767 回答
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_CONCATNOT FIND_IN_SET. 这让我得到不在链接表中的选项。

演示:http ://sqlfiddle.com/#!2/ca937/87

于 2012-10-25T23:59:32.820 回答