3

私はかなり単純なシナリオで立ち往生していますが、しばらくの間頭を悩ませた後でも、解決策を見つけることができませんでした...これが私が持っているものです.

次のデータを含む2つのテーブルがあります。

Trip (ID, Status)
30063   SUBMITTED
30066   SUBMITTED
30067   ASSIGNED
30068   SUBMITTED

AgentTripAssignment(TripId, AgentId, IsRejected)
30063   5   1
30063   2   0
30066   3   0
30066   4   0
30067   1   0
30067   2   0
30067   3   0

私がやりたいことは次のとおりです。

  • ステータスが SUBMITTED で、トリップのエントリが他のテーブルに存在する場合、AgentTripAssignment テーブルで IsRejected のカウント = 1 が 0 であるトリップ テーブルからトリップ ID を返します。ケース)と

  • ステータスが SUBMITTED でエントリが AgentTripAssignment テーブルに存在し、IsRejected = 1 のカウントが 2 番目のクエリでテーブルに少なくとも 1 回表示されているトリップ テーブルからトリップ ID を返します (この場合、エージェントが拒否されたため....30063)。

その他の注意点として、30067 の場合のようにステータスが ASSIGNED に変わると、3 人のエージェントが出張リクエストに割り当てられなくなるまで、出張のステータスは SUBMITTED のままになります。

どんな助けでも大歓迎です!

4

4 に答える 4

2

ケース 1: 出張が提出され、「却下」された割り当てはありません

これは、指定された旅行の割り当てがない場合を処理するために、割り当ての左結合を使用しています。拒否された状態の割り当ての数が 0 でない場合、その割り当ては除外されます。

SELECT t.ID
FROM Trip AS t
LEFT JOIN AgentTripAssignmentx AS at
    ON at.TripId = t.ID
WHERE t.Status = 'SUBMITTED'
GROUP BY t.ID
    HAVING COUNT(CASE WHEN at.IsRejected = 1 THEN 1 ELSE NULL END) = 0

ケース 2:出張が提出され、割り当てが「却下」された

上記と同様ですが、内部結合を使用し、割り当てが拒否されていない旅行を除外します。

SELECT t.ID
FROM Trip AS t
JOIN AgentTripAssignmentx AS at
    ON at.TripId = t.ID
WHERE t.Status = 'SUBMITTED'
GROUP BY t.ID
    HAVING COUNT(CASE WHEN at.IsRejected = 1 THEN 1 ELSE NULL END) > 0
于 2013-05-23T23:36:08.353 に答える
0

これは、準結合 (行をフィルタリングするが、データへのアクセスを提供せず、行の重複を引き起こさない結合) で非常に簡単に実行されます。最初のリクエストでは、アンチセミジョインを次に示します。

SELECT T.*
FROM
   dbo.Trip T
WHERE
   T.Status = 'SUBMITTED'
   AND NOT EXISTS (
      SELECT *
      FROM dbo.AgentTripAssignment AT
      WHERE
         T.ID = AT.TripId
         AND AT.IsRejected = 1
   )
;

SQL Fiddle でライブ デモを見る

これは非常に単純に、"次のテーブルTripに (ID に基づいて) 一致する行が存在しないAgentTripAssignmentテーブルのすべての行を表示する" と読みますIsRejected = 1

2 番目のクエリでは、ほぼ同じです。単に、AND NOT EXISTSEXISTS少なくともTrip1 つの一致する行 (ID に基づく)AgentTripAssignmentIsRejected = 1".

EXISTS私が準結合構文を好む理由は、正確なインデックスによってはパフォーマンスが向上することが多いからです。また、データベース開発者が有益だと思う方法で考えるのにも役立ちます。また、重複を修正するために a を追加する必要がないという利点もありDISTINCT、必要なテーブルからすべての行を返すことができるため、集計メソッドの問題を回避できます (aGROUP BYにテーブル内のすべての列を含める必要がある場合)。 .

于 2013-05-23T23:42:28.750 に答える
0

これは、最初の箇条書きを満たす (SQL Server 構文の) 例です。

ロジックを説明するためにクエリを分割しました。(最初の 2 つのテーブル ステートメントは、データ テーブルのサンプルです)

WITH T AS ( -- Sample data
    SELECT 30063 AS ID, 'Submitted' as Status
    UNION ALL SELECT 30066, 'Submitted'
    UNION ALL SELECT 30067, 'Assigned'
    UNION ALL SELECT 30068, 'Submitted'
), A AS ( -- Sample data
    SELECT 30063 AS ID, 5 AS AgentID, 1 AS IsRejected
    UNION ALL SELECT 30063, 2, 0
    UNION ALL SELECT 30066, 3, 0
    UNION ALL SELECT 30066, 4, 0
    UNION ALL SELECT 30067, 1, 0
    UNION ALL SELECT 30067, 2, 0
    UNION ALL SELECT 30067, 3, 0
), TPres AS ( -- get list of all IDs present in A table.
    SELECT DISTINCT A.ID
    FROM A
), RejCnt AS ( -- get List of all items with a rejected status
    SELECT DISTINCT A.ID
    FROM A
    WHERE IsRejected=1
)
SELECT T.ID
FROM T
    JOIN TPres ON TPres.ID=T.ID -- Filter out where entry for trip is in the other table.
    LEFT JOIN RejCnt ON RejCnt.ID=T.ID -- Used to Determine if IsRejected is Zero
WHERE T.Status='Submitted' -- Where status=Submitted
    AND RejCnt.ID IS NULL -- Has no rejected entries
于 2013-05-23T23:30:03.593 に答える