Mysql 我不断获得总工作作为回报

Posted

技术标签:

【中文标题】Mysql 我不断获得总工作作为回报【英文标题】:Mysql I keep getting total jobs in return 【发布时间】:2012-05-08 21:44:49 【问题描述】:

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

【问题讨论】:

关于这个查询,我突然想到了一些事情。 1)使用正确的连接。隐式连接会导致大量问题(我怀疑它实际上与此有关)。 2) 预先计算 NOW() - 30 天,然后使用该值与 j.createdAt 进行比较。这样,您可以避免全表扫描(如果 j.createdAt 被索引)。 我需要获得仍然少于 30 天的工作的完整列表。我不知道你所说的 Precalculate NOW() 是什么意思? 由于 NOW() 的值是不断变化的,mysql 必须比较重新计算每一行。这意味着即使没有 DATE_ADD,也需要进行全表扫描。基本上,你有这个:a + b < c。但是,a 可以被索引,这意味着如果你可以得到一个只涉及 a 而不是 a 的函数的比较,你可以利用这个索引。换句话说,您想将其更改为a < c - b。但是,c 是不断变化的,因此您仍然必须进行完整的表扫描(索引只能与常量一起使用)。 那么,我所说的简短版本是什么?计算 now() - php 中的 30 天。基本上 j.createdAt $date = date('Y-m-d H:i:s', strtotime('now -30 days)); @Corbin:NOW() 的值在查询(或触发器或存储过程)期间永远不会改变。 SYSDATE() 发生了变化。涉及NOW() 的谓词可能是sargable(原始查询中的那个当然不是,但不是因为NOW())。 【参考方案1】:
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 条记录,这是正确的。但这可以在没有 DISTINCT 的情况下完成 @Lalajee:你对DISTINCT有什么看法? 过去被告知要避免这种情况。 @Lalajee:我特此免除您的此限制。 DISTINCT 可以使用(至少在这个查询中)。 谢谢。你不知道你为我做了什么。我试图解决这个问题一周现在我无法看到为什么我的查询返回错误的答案。非常感谢。【参考方案2】:

您的查询应该返回所有雇主的所有工作的计数,但有一些条件必须匹配才能显示。正如您所使用的,隐式连接是 INNER JOIN。这要求所有条件都匹配才能包含行。这意味着它只返回“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 天,以查看它是否大于 NOW()。 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 个人免于繁重的工作。

【讨论】:

感谢您修复我的日期值。抱歉,我的问题是我需要返回已发布工作且工作时间少于 30 天的雇主的号码。但是我不断获得 604 条记录,而我应该只获得 1 条记录,因为我的雇主表中只有 1 个雇主。 我确实有 604 个职位由该雇主发布。 @Lalajee,我更新了我的答案以提供类比。你的 GROUP 子句去哪儿了? 即使使用 Group 我仍然获得 604 条记录 我几乎尝试了每件事,但仍然得到相同的结果。我认为我的查询缺少某些内容。【参考方案3】:

我怀疑“SELECT count(*) as total”是您的问题。您要求 SQL 计算返回的所有内容。请注意您正在“选择”的内容,因为这是唯一会返回给您的内容。

您没有完全解释您要在这里实现的目标。 “我需要找到所有的雇主”是含糊不清的,很难理解。您想获取有关雇主的哪些数据?他们的身份证?他们的总工作量?

【讨论】:

这只是我分页的总记录。我需要让系统返回在现场发布职位的雇主总数。

以上是关于Mysql 我不断获得总工作作为回报的主要内容,如果未能解决你的问题,请参考以下文章

如何将字符串类型的工作日数据项(日期、工作时间)列表减少为每个工作日范围字符串的列表,每个字符串都有总工作时间?

如何在 JIRA 仪表板小工具的每周细分中显示工作日志?

多个并且在mysql中工作或不工作[重复]

如何获得mysql随机整数范围?

何为薪酬

Spark RDD 默认分区数量 - repartitions和coalesce异同