2016-05-12 84 views
0

我有这个查询,这是从片段/想法周围在这里 - 我不是在更先进的SQL的专家呢。我希望你关注的部分是:WHERE ... l.status =“主动”SQL查询 - 问题与WHERE语句

SELECT l.*, COUNT(c.id) AS callsNum 
FROM leads AS l 
LEFT JOIN calls AS c ON c.lead = l.id 
WHERE l.pool IN ($pools) AND l.status='active' AND l.center='$center' 
GROUP BY l.id 
ORDER BY callsNum ASC, l.id ASC 
LIMIT 0,1 

我不能让自己的错误,但如果有一个状态是导致一些人经历了错误不“积极”已经出现。

任何人都可以发现错误?我想代码也可以更好,任何建议都是值得欢迎的 - 如果不清楚代码应该做什么,请随时询问。

更新:

感谢您的回复。我很高兴你认为该查询应该可以工作。我想我需要添加一些更多的信息。

该系统适用于小型呼叫中心。该查询将从选定的池中获取下一个线索,即调用者应该调用的线索。在对PHP文件的相同AJAX调用中,“下一个领先”被标记为“处理”以避免多个调用者获得该samme领导。

正如所指出的那样,如果两个呼叫者在同一时间按下“获得下一首”按钮,技术上可能会发生问题。但他们向我报告说,即使他们只有两名来电者同时呼叫同一个联络人,他们也经常得到相同的线索。如果他们是4人,更经常。

因此,我在这个查询之后加入了一些代码行,它再次检查lead的status ='active' - 如果不是,它会出现一个错误(以防止多个调用者在同时)。这个错误经常发生,因此我怀疑这个查询有什么问题。

领导不会多次出现是非常重要的。有什么建议么?

相关的代码(FULL)

这里是按要求较长的代码示例。最后的错误通常只有2-4人使用它(在一个相当快的服务器上)。

// Get next lead 
$stmt = $db->prepare(" 
    SELECT l.*, COUNT(c.id) AS callsNum 
    FROM leads AS l 
    LEFT JOIN calls AS c ON c.lead = l.id 
    WHERE l.pool IN ($pools) AND l.status='active' AND l.center='$center' 
    GROUP BY l.id 
    ORDER BY callsNum ASC, l.id ASC 
    LIMIT 0,1"); 
$stmt->execute(); 
$res = $stmt->get_result(); 

if($res->num_rows > 0) { 

    while($row = $res->fetch_assoc()) { 

     // Set as "processing" to avoid simultaneous call from multiple bookers 
     $stmt = $db->prepare("UPDATE leads SET status='processing' WHERE status='active' AND id=? AND center='$center'"); 
     $stmt->bind_param("i", $row["id"]); 
     $stmt->execute(); 
     $affectedRows = $stmt->affected_rows; 
     if($affectedRows != 1) { 
      echo 'ERROR. Please reload.'; 
      die; 
     } 

    } 
} 
+0

您选择非聚合列,这在技术上是坏的,但除了这一点,我看不出有什么问题。你目前的产出是多少? –

+1

@TimBiegeleisen。 。 。在这种情况下应该没问题,假设'id'在'leads'中是唯一的。 –

+0

看起来没问题。你可能会得到'active'或'active'列吗? – artm

回答

0

WHERE部分,它说我们需要它的属性有一些特殊的特性,以满足这三个条件,如下表线索:

  1. l.pool应该是集($pools
  2. l.status应激活
  3. l.center应该是$center
+0

这是一个答案? – Strawberry

1

你说:

我不能让自己的错误,但如果与状态不是“活动”已经拿出导致一些人经历了错误 。

这可能是并发问题,其中当用户A得到线索(使用查询)的列表,并阅读它们,另一个用户(用户B),同时标志着引线为“不活动”之一。所以当用户A打开领先时,它被标记为“非活动”。 如果用户A刷新导致不再存在的列表。

1

我不知道这是否将会减少并发问题,但你可以尝试一些这第一个“储备”引:

UPDATE leads 
SET status = CONCAT('Processing ', somesortofcalleridentifier) 
WHERE l.pool IN ($pools) AND l.status='active' AND l.center='$center' 
LIMIT 1; 

我说这一点,因为你原来的按分组结果排序可能会使它比我所显示的要复杂一些。

随后跟进:

SELECT l.*, COUNT(c.id) AS callsNum 
FROM leads AS l 
LEFT JOIN calls AS c ON c.lead = l.id 
WHERE status = CONCAT('Processing ', somesortofcalleridentifier) 
; 
+0

谢谢!如果使用此代码,它如何获得并发性问题?对我来说它看起来相当不错。 –

+0

它不会有任何我知道的,但大部分时间我在MySQL上花费的时间早于一个项目,并且(可以猜到)继续忽略事务的可用性等等。虽然我不指望有问题,但我不能100%保证不会有问题。 – Uueerdo

+0

@ChristianBundgaard它基本上将状态字段变成一个临时互斥体;但UPDATE越复杂,我担心的操作越不会有效原子化。 – Uueerdo