1

2 つの MySQL テーブルがあります

Payments:
| employeeID | period_begin  | period_end   |

Services:
| serviceID  | date      | employeeID   |

Payments で説明されている期間範囲内にない日付を持つ特定の従業員によって実行されたすべての serviceID を見つける必要があります。たとえば、従業員 10000 の支払いとサービスに関する次のレコードがあるとします。

Payments:
| employeeID    | period_begin  | period_end    |
...
| 10000     | 2013-05-01    | 2013-05-16    |
| 10000     | 2013-05-17    | 2013-06-02    |
| 10000     | 2013-07-01    | 2013-07-16    |
| 10000     | 2013-07-17    | 2013-08-02    |   
...

Services:
| serviceID         | date          | employeeID    |
...
| 2001      | 2013-01-01    | 10000     |
| 2002      | 2013-05-15    | 10000     |
| 2003      | 2013-06-01    | 10000     |
| 2004      | 2013-07-10    | 10000     |
| 2005      | 2013-08-01    | 10000     |
...

出力は

2001年、2003年、2005年

サービス 2002、2004 の日付は Payments テーブルの間隔の 1 つにあるためです。

何か案は?サービスの日付が Payments テーブルに記録されている間隔の 1 つに含まれていないことを確認するのに問題があります。現在、employeeID で Services and Payments に参加し、日付条件を記載していますが、正しい答えが得られません。私はおそらく別の条件で参加する必要があります。

select distinct serviceID from Services as X left join Payments as Y on
(X.employeeID=Y.employeeID AND (X.date < Y.period_begin OR X.date > Y.period_end))
where X.employeeID='10000';

動かない。

4

3 に答える 3

2
... AND X.date < Y.period_begin and X.date > Y.period_end

明らかに不可能です (日付を開始日より前にすることはできず終了日より後にすることはできません...)

おそらく次のように書きたいと思うでしょう:

... AND (X.date < Y.period_begin or X.date > Y.period_end)

「OR」式は括弧で囲んでください。これは演算子の優先順位に関して重要であり、読みやすさが向上すると思います。

編集:コメントで@BigToachが示唆しているように、使用できますNOT BETWEEN ... AND ...ANDそのコンテキストで単語があまり混乱しない場合):

... AND (X.date NOT BETWEEN Y.period_begin AND Y.period_end)
于 2013-08-05T09:20:58.663 に答える
0

「支払い範囲にないサービスを選択する」という主な問題に関しては、 a使用LEFT JOINして、対応する支払い範囲を持たない行のみを保持できます。

SELECT Services.* FROM Services
 LEFT JOIN
  (SELECT serviceID,period_begin FROM Services 
     JOIN Payments
     USING (employeeID)
     WHERE employeeID = @EID
     AND the_date BETWEEN Payments.period_begin AND Payments.period_end
  ) AS X
 USING (serviceID)
 WHERE employeeID = @EID
 AND period_begin is NULL;

または、サブクエリを使用します -- やや読みやすくなりますが、通常は効率が低下します。

SELECT Services.* FROM Services
WHERE employeeID = @EID
AND serviceID NOT IN (SELECT serviceID FROM Services JOIN Payments
                      USING (employeeID)
                      WHERE employeeID = @EID
                      AND the_date BETWEEN Payments.period_begin AND Payments.period_end);

http://sqlfiddle.com/#!2/a3557/11を参照してください。

于 2013-08-05T16:06:18.377 に答える
0

BigToach と Sylvain Leroux が指摘したように、AND と OR を混同する論理タイプミスが明らかにありました。ただし、修正しても、そのクエリはまだ正しい答えを与えません。最初に特定の間隔に含まれるすべてのサービス ID を見つけてから、すべてのサービス ID のリストからそれらを除外することで、適切なソリューションを得ることができました。

    select distinct serviceID from Services as X left join Payments as Y on
    (X.employeeID=Y.employeeID) where X.employeeID='10000' 
    and X.serviceID not in (
       select serviceID from Services as Z join Payments as W on
       (Z.employeeID=W.employeeID and 
       (Z.date between W.period_begin and W.period_end)) 
       where Z.employeeID='10000'
    );

ただし、このクエリは実際には2つのクエリを実行しているため、あまりきれいではありませんが、基本的にはSylvain Lerouxの最初の回答と同じで、おそらく人間が読めるほうが少し多いでしょう. まだ誰も見ていない別の方法があるかもしれません。Sylvain のサブクエリは実に素晴らしいものです。

于 2013-08-05T21:07:53.227 に答える