返回id,其他表上与该id相关联的值的计数为0

时间:2013-05-23 20:02:07

标签: sql-server tsql

我一直被困在一个相当简单的场景中,但即使在我搔了一段时间之后我也找不到解决方案......这就是我所拥有的。

我有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

我想做的是:

  • 从行程表中返回行程ID,状态为SUBMITTED,如果其他表中存在行程条目,则在具有1个查询的AgentTripAssignment表中,IsRejected = 1的计数为零(作为新查询....在特定情况下为30066,30068)和

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

其他注意事项是,行程状态保持提交,直到3个座席未分配给行程请求,即当状态变为ASSIGNED时,就像30067一样。

非常感谢任何帮助!

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分: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
   )
;

See a Live Demo at SQL Fiddle

这非常简单地读作,“显示表Trip中的所有行,其中表AgentTripAssignment中没有匹配的行(基于ID)IsRejected = 1”。

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

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