使用单个T-SQL语句查找负载最少的实时代理

时间:2013-08-06 14:47:55

标签: sql-server sql-server-2008-r2

我有几个代理和一个数据库表(BackgroundJobWork)记录每个代理的工作负载。该表将包含每个工作项的条目。

当我想要分配新的工作项时,我首先检查此表并选择已分配给它的工作量最少的代理。

当代理通过工作项时,它会将其状态更改为分配以外的其他内容。

有一个扭曲。代理在另一个表(BackgroundJobService)中报告其心跳。如果代理未能及时报告,则该表中的状态将设置为“无响应”。用于确定哪个代理程序加载最少的SQL查询必须仅检查“实时”代理程序。

这是我的SQL查询,用于选择加载最少的实时代理:

SELECT bjw.AllocatedAgentHostName HostName, bjw.AllocatedAgentServiceName ServiceName,
  SUM(CASE WHEN bjw.WorkStatusTypeId IN (2,3,4) THEN 1 ELSE 0 END) AS InProgress
  FROM BackgroundJobWork bjw, BackgroundJobService bjs
  WHERE bjw.AllocatedAgentHostName = bjs.HostName
        AND bjw.AllocatedAgentServiceName = bjs.ServiceName
        AND bjs.AgentStatusTypeId = 2
  GROUP BY bjw.AllocatedAgentHostName, bjw.AllocatedAgentServiceName
  ORDER BY InProgress

其中:

  • BackgroundJobWork.WorkStatusTypeId中的2,3或4对应于分配给特定代理(由HostName + ServiceName字段对表示)
  • BackgroundJobService.AgentStatusTypeId of 2对应于在线客服

不幸的是,我的查询有一个错误。如果代理在BackgroundJobWork表中根本没有条目,会发生什么?在这种情况下,我的查询生成的结果中省略了该代理,即使它是实时代理。这是一个丑陋的错误。

我应该以另一种方式转换我的SQL - 而不是查看工作负载表(BackgroundJobWork)然后将其与实时状态表(BackgroundJobService)匹配我应该首先看一下后者并与前者匹配,这是因为实时状态表保证每个代理只有一行。

但我不确定,直到现在还没有产生令人满意的查询。

2 个答案:

答案 0 :(得分:0)

  

我应该以另一种方式转换我的SQL ......

就这样。尝试左边加入BJW对抗BJS,而不是像现在一样将BJS加入BJW。

SELECT bjs.HostName HostName, bjs.ServiceName ServiceName,
  SUM(CASE WHEN bjw.WorkStatusTypeId IN (2,3,4) THEN 1 ELSE 0 END) AS InProgress
  FROM BackgroundJobService bjs
  LEFT JOIN BackgroundJobWork bjw 
        ON bjw.AllocatedAgentHostName = bjs.HostName
        AND bjw.AllocatedAgentServiceName = bjs.ServiceName
  WHERE bjs.AgentStatusTypeId = 2
  GROUP BY bjs.HostName, bjs.ServiceName
  ORDER BY InProgress

另外,出于可维护性的原因,请考虑明确使用INNER JOIN而不是过时的逗号语法。

答案 1 :(得分:0)

请尝试下面提到的查询。在此查询中,“Union”之后的部分是在BackgroundJobWork中但在BackGroundJobService中不存在的代理列表,并且因为它们没有运行任何服务,所以您可以在那里提及任何其他值:

SELECT bjw.AllocatedAgentHostName HostName, bjw.AllocatedAgentServiceName ServiceName,
SUM(CASE WHEN bjw.WorkStatusTypeId IN (2,3,4) THEN 1 ELSE 0 END) AS InProgress
FROM BackgroundJobService bjs
JOIN BackgroundJobWork bjw 
ON bjw.AllocatedAgentHostName = bjs.HostName
AND bjw.AllocatedAgentServiceName = bjs.ServiceName
WHERE bjs.AgentStatusTypeId = 2
GROUP BY bjs.HostName, bjs.ServiceName
ORDER BY InProgress
UNION
select hostname,'No Service Currently',0 from BackgroundJobService where AgentStatusTypeId = 2
and hostname not in(Select distinct AllocatedAgentHostName from BackgroundJobWork)