Mysql 返回大型结果的组合SQL查询
我需要从mysql数据库收集数据,以使我们能够向在给定天数内不活跃的客户发送促销电子邮件,但仅限于那些从未向我们注册过促销点的客户。该数据库相当大,拥有超过50000名客户,仅查询未注册积分的客户的客户id就需要一个多小时。 所以我想,如果我把搜索范围缩小到那些在给定时间内没有登录的客户,然后只对那些客户id进行搜索,速度会更快。但是,我尝试组合这两个查询时完全失败,返回的操作数应包含1列错误 考虑到我在查询中需要接收的数据,是否有可能实现 第一个需要1小时的查询:Mysql 返回大型结果的组合SQL查询,mysql,sql,performance,join,Mysql,Sql,Performance,Join,我需要从mysql数据库收集数据,以使我们能够向在给定天数内不活跃的客户发送促销电子邮件,但仅限于那些从未向我们注册过促销点的客户。该数据库相当大,拥有超过50000名客户,仅查询未注册积分的客户的客户id就需要一个多小时。 所以我想,如果我把搜索范围缩小到那些在给定时间内没有登录的客户,然后只对那些客户id进行搜索,速度会更快。但是,我尝试组合这两个查询时完全失败,返回的操作数应包含1列错误 考虑到我在查询中需要接收的数据,是否有可能实现 第一个需要1小时的查询: SELECT c.custo
SELECT c.customers_id
FROM customers c
LEFT JOIN codes_redeem_history pc
ON pc.customer_id=c.customers_id
WHERE pc.customer_id IS NULL
给定时间内客户的第二次查询:
SELECT ci.customers_info_date_of_last_logon, ci.customers_info_id, c.customers_email_address, c.customers_lastname, c.customers_firstname
FROM customers c, customers_info ci
WHERE c.customers_id = ci.customers_info_id
GROUP BY c.customers_email_address
HAVING max(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY)
ORDER BY c.customers_lastname, c.customers_firstname ASC
我如何尝试,但未能将它们结合起来:
SELECT c.customers_id
FROM customers c
LEFT JOIN codes_redeem_history pc
ON pc.customer_id=c.customers_id
WHERE pc.customer_id IS NULL
AND c.customers_id
IN
(Select ci.customers_info_date_of_last_logon, ci.customers_info_id, c.customers_email_address, c.customers_lastname, c.customers_firstname
FROM customers c, customers_info ci
WHERE c.customers_id = ci.customers_info_id
GROUP BY c.customers_email_address
HAVING max(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY)
ORDER BY c.customers_lastname, c.customers_firstname ASC)
我可以从错误消息中看出,它不允许在INSELECT中进行如此复杂的查询
查询的一部分,但我不知道如何重新安排它,或者它是否可行
您的SQL专家有什么建议吗
谢谢
在需求稍微改变之后,我可以在这方面多提供一些帮助
在前面的回答之后,我尝试稍微更改查询以允许选择时间跨度,而不是将其固定为30天。我曾经让MAX ci.customers\u info\u date\u of\u last\u logon>='$淹没。”$ndate是保存所需日期的var。很明显,它不起作用,因为约会和30天不一样。我似乎无法使用WHERE条件来代替MAX.Any solutions?第一个查询花费太长时间来完成的原因是,我几乎可以肯定,因为您在定义它们的关系的列上缺少索引,请通过执行以下行来更改表
ALTER TABLE codes_redeem_history ADD INDEX (customer_id);
ALTER TABLE customers ADD INDEX (customers_id);
ALTER TABLE customers_info ADD INDEX (customers_info_id);
完整查询
SELECT c.customers_id
FROM customers c
LEFT JOIN codes_redeem_history pc
ON pc.customer_id=c.customers_id
LEFT JOIN
(
Select c.customers_id
FROM customers c
INNER JOIN customers_info ci
ON c.customers_id = ci.customers_info_id
GROUP BY c.customers_email_address
HAVING MAX(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY)
) d ON c.customers_id = d.customers_id
WHERE pc.customer_id IS NULL AND
d.customers_id IS NOT NULL
更新1
函数中的子查询返回多个列;您需要修改它以只返回一列。最好有查询的解释。。。奇怪的是,你的第一个查询需要这么长时间,你有索引吗?@m4573r没有,没有索引,而且“代码”历史表包含400210行,因此它太慢了。先生,你是一个绝对的钻石。添加索引使现在运行第一部分查询的时间相差了0.0006秒!但是,完整的sql返回检查与您的MySQL服务器版本对应的手册,以了解在c.customers\u id=d.customers\u id上使用接近'd'的正确语法,其中pc.customer\u id为NULL,并且在第13行“哦,对不起,我错过了类型。它应该是subdatenow,间隔30天我现在将两个查询翻转过来,以便从customers c LEFT JOIN codes_Redeme_history pc ON pc.customer_id=c.customers_id其中pc.customer_id为空部分过滤原始第二个查询的结果?太棒了。回答被接受并且+1。总查询时间为0.0037秒。完美答案看看索引有多强大。。但是不要滥用它们,只要你想添加它们,它就会导致你慢慢地插入、更新和删除。。。
SELECT c.customers_id
FROM customers c
INNER JOIN customers_info ci
ON c.customers_id = ci.customers_info_id
LEFT JOIN codes_redeem_history pc
ON c.customers_id = pc.customer_id
WHERE pc.customer_id IS NULL
GROUP BY c.customers_email_address
HAVING MAX(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY)