4

私は3つのテーブルを持っています。1 つはサービスの表です。各サービスには、オプション テーブルにあるいくつかのオプションがあります。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つのオプションすべてを持たないcontactIDと、欠落している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 の行を取得する方法を理解する必要があります。

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_CONCAT混合NOT FIND_IN_SETです。これにより、リンク テーブルにないオプションを取得できます。

デモ: http://sqlfiddle.com/#!2/ca937/87

于 2012-10-25T23:59:32.820 に答える