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 的行程表中返回行程 ID,如果行程条目存在于其他表中,则在 AgentTripAssignment 表中 IsRejected = 1 的计数为零,其中有 1 个查询(作为给定的新查询....30066,30068案例)和

  • 从状态为 SUBMITTED 的行程表中返回行程 ID,并且 AgentTripAssignment 表中存在条目,其 IsRejected = 1 的计数在第二个查询的表中至少出现一次(在给定的情况下,代理被拒绝 ....30063)

需要注意的另一点是,行程的状态保持已提交,直到 3 个代理未分配到行程请求,此时状态更改为已分配,如 30067 的情况。

任何帮助都感激不尽!

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 a.tripid
from agenttripassignment a
join trip b on a.tripid = b.tripid
where b.status = 'submitted'
group by a.tripid
having max(a.isrejected) = 0

同样与 1

于 2013-05-23T20:17:12.497 回答
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 回答
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”。

对于您的第二个查询,它几乎完全相同,只需更改AND NOT EXISTSEXISTS:“显示表Trip中至少有一个匹配行(基于 ID)存在于AgentTripAssignment具有IsRejected = 1”的表中的所有行。

我更喜欢EXISTS半连接语法的原因是它通常可以提供更好的性能,具体取决于确切的索引。它还可以帮助数据库开发人员以我认为有益的方式进行思考。它还具有不必附加 aDISTINCT来修复重复的好处,并且它通过允许您从所需表中返回所有行来避免聚合方法的问题(当 aGROUP BY必须包含表中的所有列时) .

于 2013-05-23T23:42:28.750 回答