我要求从mysql数据库收集数据,以便我们能够向在给定天数内没有活动的客户发送促销电子邮件,但只向那些从未在我们这里注册过促销点的客户发送。数据库相当大,超过50,000个客户,并且检查那些没有注册点的客户的查询需要一个多小时来单独处理。 所以我认为,如果我将其缩小到在给定时间内没有登录的客户,然后仅对那些customer_id进行搜索,那么它会更快。但是,我尝试组合这两个查询是完全失败,返回“操作数应该包含1列”错误。
考虑到我需要在查询中收到的数据,是否可以实现。
首先需要1小时的查询:
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)
我可以从错误消息中看到它不会在IN(SELECT)中允许这样复杂的查询 查询的一部分,但我不知道如何重新排列它,或者它是否可行。
您对SQL Gurus有何建议?
由于
在稍微改变要求之后,我可以对此提供更多帮助。
除了早先的回答之外,我还尝试稍微更改查询以允许选择时间跨度,而不是在30天时修复。我使用了HAVING MAX(ci.customers_info_date_of_last_logon)&gt; ='“。$ ndate。”',其中$ ndate是一个包含所需日期的var。显然它不起作用,因为日期与30天不一样。我似乎无法使用WHERE条件代替HAVING MAX。任何解决方案?
答案 0 :(得分:2)
第一个查询需要很长时间才能完成的原因是,我几乎可以确定它,因为你缺少定义它们关系的列的索引,通过执行以下行来改变表,
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
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)