Php Mysql我不断得到总的工作回报

Php Mysql我不断得到总的工作回报,php,mysql,mysql5,Php,Mysql,Mysql5,我有一个sql查询,我想从中获取总记录 我有一个雇主,这个雇主有600份工作 我需要得到所有的雇主,但出于某种原因,我的查询是返回雇主发布的总工作岗位 请让我知道我在这个问题上出了什么问题 SELECT count(c.id) as total FROM employer as c INNER JOIN job as j ON j.employerIDFK = c.id WHERE c.isActive=1 AND c.status=1 AND j.isActive=1 AND j.b

我有一个sql查询,我想从中获取总记录

我有一个雇主,这个雇主有600份工作

我需要得到所有的雇主,但出于某种原因,我的查询是返回雇主发布的总工作岗位

请让我知道我在这个问题上出了什么问题

SELECT count(c.id) as total 
FROM employer as c INNER JOIN  job as j ON j.employerIDFK = c.id 
WHERE c.isActive=1 AND c.status=1 
AND j.isActive=1 
AND j.beenActive=1 
AND j.status=1 
AND DATE_ADD( j.createdAt, INTERVAL 30 DAY ) > NOW()
我怀疑“选择计数(*)作为总数”是您的问题。您要求SQL计算返回的所有内容。注意你正在“选择”的东西,因为这是唯一会返回给你的东西


你没有很好地解释你在这里想要实现什么。“我需要得到所有的雇主”是含糊不清的,很难理解。你想从雇主那里得到什么数据?他们的身份证?他们的工作总数?

您的查询应该返回所有雇主的所有工作的计数,但有一些条件必须匹配才能显示出来。您正在使用的隐式联接是内部联接。这要求所有条件都匹配,以便包含行。这意味着它只返回“isActive”、“beenActive”、“status=1”和createdAt在过去不到30天的作业,其中员工是“isActive”和“status=1”。检查您的数据,看看这是否是您想要的

SELECT c.id AS employerID, count(*) as total 
FROM employer as c, job as j 
WHERE c.isActive=1 AND c.status=1 
AND j.employerIDFK = c.id 
AND j.isActive=1 
AND j.beenActive=1 
AND j.status=1 
AND DATE_ADD( j.createdAt, INTERVAL 30 DAY ) > NOW()
GROUP BY c.id
至于其他人对createdAt上的过滤器的看法,MySQL将首先计算NOW()(只计算一次)。然后,它会在每个createdAt日期上加上30天,以查看是否大于现在()。MySQL有时会自动对此进行优化,这取决于您的版本和其他一些因素,但一般来说,针对每一行的createdAt日期执行函数以将其与常量表达式进行比较是不好的,因为MySQL无法利用createdAt列上的索引

因此,您应该转换:

AND DATE_ADD( j.createdAt, INTERVAL 30 DAY ) > NOW()
为此:

AND j.createdAt > DATE_ADD( NOW(), INTERVAL -30 DAY )
这使得j.createdAt列成为普通列,因此MySQL现在可以利用该列的任何索引来查找过去少于30天的日期

这相当于站在一个有100人的房间里,让他们在生日的基础上再加30天,然后问谁的计算日期大于今天。你刚刚让100个人工作。相反,通过从今天的日期减去30天来预先计算标准,只需询问是否有人的生日大于该日期。你只需要做一次计算,这就省去了那100人的繁重工作

SELECT  COUNT(DISTINCT c.id) AS total 
FROM    employer c
JOIN    job j
ON      j.employerIDFK = c.id
WHERE   c.isActive = 1
        AND c.status = 1
        AND j.isActive = 1 
        AND j.beenActive = 1 
        AND j.status = 1 
        AND j.createdAt >= NOW() - INTERVAL 30 DAY
创建以下索引:

employer (isActive, status)
job (employerFKID)
job (isActive, beenActive, status, createdAt, employerFKID)
以便查询更快地工作

如果出于某些模糊的原因,您不愿意使用
DISTINCT
,您可以使用:

SELECT  COUNT(c.id) AS total
FROM    employer c
WHERE   c.isActive = 1
        AND c.status = 1
        AND c.id IN
        (
        SELECT  employerIDFK
        FROM    job j
        WHERE   j.isActive = 1
                AND j.beenActive = 1
                AND j.status = 1
                AND j.createdAt >= NOW() - INTERVAL 30 DAY
        )

但是,这可能效率较低,因为
MySQL
无法使
job
在此类查询中处于领先地位。

关于此查询,我有几件事要做。1) 使用适当的连接。隐式连接会导致大量问题(我怀疑它实际上与此有关)。2) 现在预计算()-30天,然后使用该值与j.createdAt进行比较。这样,您就可以避免一次完整的表扫描(如果j.createdAt被索引的话)。我不知道你所说的Precalculate NOW()是什么意思?因为NOW()的值不断变化,MySQL必须对每一行进行比较并重新计算。这意味着即使没有添加日期,也需要进行完整的表扫描。基本上,您有:
a+b
。然而,a可以被索引,这意味着如果您可以得到一个只涉及a而不涉及a函数的比较,那么您可以利用这个索引。换句话说,您希望将其更改为
a
。然而,c是不断变化的,所以你仍然必须做一个完整的表扫描(索引只能与常量一起工作)?立即计算()-PHP中的30天。基本上j.createdAt<$date with
$date=date('Y-m-d H:i:s',strottime('now-30天))
@Corbin:
NOW()
的值在查询(或触发器或存储过程)期间不会更改。更改的是
SYSDATE()
。涉及
NOW()
的谓词可能是可搜索的(原始查询中的谓词当然不是,但不是因为
NOW()
)。这只是我分页的总记录。我需要要求系统返回在网站上有职位的雇主的总数。谢谢你们为我的日期值修复。对不起,我的问题是,我需要返回的雇主已经张贴了工作,他们的工作少于30天的数字。但我一直得到604条记录,我应该只得到一条记录,因为我的雇主表中只有一个雇主。我确实有604份工作是由这个雇主发布的。@Lalajee,我更新了我的答案以提供一个类比。你的团体条款到哪里去了?即使是团体,我仍然获得了604条记录。我尝试了几乎所有的事情,但仍然得到了相同的结果。我想我的查询遗漏了什么。这确实有效。我现在只得到一张正确的记录。但是,这可以不做吗DISTINCT@Lalajee:你对DISTINCT有什么反对意见?过去有人告诉过你要避免这种情况。@Lalajee:我特此免除你的这种限制
DISTINCT
可以使用(至少在这个查询中是这样)。谢谢。你不知道你为我做了什么。我本周一直在试图解决这个问题,但现在我不明白为什么我的查询返回了错误的答案。非常感谢你。