我有一个SQL查询,我需要帮助......
基本上我需要使用两个表。一个包含客户帐户,另一个包含客户服务代表与客户交互的日志。我希望此查询为我提供过去14天内没有日志条目(交互)的任何帐户的ID。我还想过滤掉几个不相关的代表帐户(使用assignedto
字段,如您所见)。此外,日志表中的日期格式是非标准的,我无法更改它,因为我还没有编写的软件也使用这个数据库。
这两个表格为cm.dbs (customer accounts)
和cm.log (interaction log)
。
这是我提出的查询,但需要 FOREVER 才能运行。子查询工作得很好,只需要几分之一秒,但是当主查询与子查询一起运行时,它的速度非常慢。我猜这是因为子查询正在为主查询中的每一行运行(并且它不需要)但我对如何解决这个问题毫无头绪,因为我不是SQL的专家,我知道足够创建基本到中间查询,这不是我以前做过的事情。
这是我到目前为止创建的查询:
SELECT id FROM cm.dbs WHERE id NOT IN (SELECT filenumber FROM cm.log
WHERE STR_TO_DATE(logdate, '%m/%d/%Y')
BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY)
AND NOW()
GROUP BY filenumber)
AND assignedto != 'OLD_ACCTS'
AND assignedto != 'HOUSE_ACCOUNTS'
AND assignedto != 'PAID_ACCOUNTS';
子查询在过去两周内查找日志表中包含条目的所有帐户。它完美地完成了这项工作。然后诀窍是让主查询找到所有没有条目的帐户。
另请注意,cm.log中的filenumber
字段对应id
表中的cm.dbs
。
我可能以一种完全愚蠢的方式接近这一点而且我并不高于承认这一点。任何有关正确和有效地使这项工作的意见表示赞赏。我也很喜欢任何人建议解释的修复/更改。我不仅仅想要为我构建一个查询,我想知道我做错了什么以及如何做得更好,以便下次我能为自己解决这个问题。我很少问这样的问题,我通常会自己解决这个问题,但这让我很难过。
编辑:以下是表格中相关字段的部分架构:
cm.dbs:
id int(10) UN PK AI
title varchar(45)
firstname varchar(200)
middlename varchar(200)
lastname varchar(200)
fullname varchar(200)
address varchar(200)
address2 varchar(200)
city varchar(200)
state varchar(200)
zip varchar(50)
assignedto varchar(200)
...
cm.log:
id int(10) UN PK AI
filenumber varchar(200)
agentname varchar(200)
logtime varchar(200)
logdateandtime varchar(200)
logdate varchar(200)
logmessage mediumtext
答案 0 :(得分:0)
这是我在没有数据库架构的情况下所能做到的最好的事情,但希望能够非常接近您所寻找的(或者至少指向正确的方向):
SELECT DISTINCT dbs.id
FROM cm.dbs, cm.log
WHERE dbs.id = log.filenumber
AND STR_TO_DATE(log.logdate, '%m/%d/%Y') NOT BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY) AND NOW()
AND dbs.assignedto NOT IN ('OLD_ACCTS','HOUSE_ACCOUNTS','PAID_ACCOUNTS');
如果您有机会在查询中运行EXPLAIN并将输出添加到您的问题中,那么我们可以更好地对其进行分析(并包括数据库架构)。
答案 1 :(得分:0)
除了下面的更改之外,您的查询对我来说是正确的(因为您要检查多个assignedto
值,请使用IN
运算符,而不是将它们单独放在OR
中。)
SELECT id FROM cm.dbs WHERE id NOT IN (SELECT filenumber FROM cm.log
WHERE STR_TO_DATE(logdate, '%m/%d/%Y')
BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY)
AND NOW()
GROUP BY filenumber)
AND assignedto NOT IN ('OLD_ACCTS','HOUSE_ACCOUNTS','PAID_ACCOUNTS');
答案 2 :(得分:0)
我认为你是以错误的方式攻击这个。让我们分解你正在寻找的东西。
首先是filenumber和max logdate:
SELECT filenumber, MAX(logdate)
FROM cm.log
GROUP BY filenumber
所以现在我们只需将它加入另一个表:
SELECT filenumber, MAX(logdate), assignedto
FROM cm.log as log
INNER JOIN cm.dbs as dbs ON log.filenumber = dbs.id
GROUP BY filenumber
现在我们想对我们刚刚选择的内容应用一些条件(超过2周,而不是在这3组中):
SELECT * FROM (
SELECT log.filenumber, MAX(logdate) as logdate, assignedto
FROM cm.log as log
INNER JOIN cm.dbs as dbs ON log.filenumber = dbs.id
GROUP BY filenumber) t
WHERE logdate < DATE_SUB(NOW(), INTERVAL 14 DAY)
AND assignedto NOT IN ('OLD_ACCTS','HOUSE_ACCOUNTS','PAID_ACCOUNTS')