SQL查询 - WHERE语句问题

时间:2016-05-12 23:27:40

标签: php mysql sql

我有这个查询,这是从这里的片段/想法 - 我不是更先进的SQL的专家。我想让你关注的部分是:WHERE ... l.status ='active'

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个来电者,甚至更频繁。

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

铅不会多次出现非常重要。有什么建议吗?

相关代码(全部)

这是一个更长的代码示例。最终出现的错误通常只有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;
        }

    }
}

3 个答案:

答案 0 :(得分:1)

你说:

  

我自己无法得到错误,但有些人遇到了错误   已经出现了状态为非“活跃”的潜在客户。

这可能是一个并发问题,当用户A获取潜在客户列表(使用您的查询)并阅读它们时,另一个用户(用户B)同时将其中一个潜在客户标记为“非活动”。因此,当用户A然后打开一个潜在客户时,它被标记为“非活动”。 如果用户A刷新了一个不再存在潜在客户的列表。

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

答案 2 :(得分:0)

在Where部分,它表示我们需要表引线,其属性具有一些特殊特性,以满足以下所有三个条件:

  1. l.pool应设置为$pools
  2. l.status应该有效
  3. l.center应为$center