Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 返回大型结果的组合SQL查询_Mysql_Sql_Performance_Join - Fatal编程技术网

Mysql 返回大型结果的组合SQL查询

Mysql 返回大型结果的组合SQL查询,mysql,sql,performance,join,Mysql,Sql,Performance,Join,我需要从mysql数据库收集数据,以使我们能够向在给定天数内不活跃的客户发送促销电子邮件,但仅限于那些从未向我们注册过促销点的客户。该数据库相当大,拥有超过50000名客户,仅查询未注册积分的客户的客户id就需要一个多小时。 所以我想,如果我把搜索范围缩小到那些在给定时间内没有登录的客户,然后只对那些客户id进行搜索,速度会更快。但是,我尝试组合这两个查询时完全失败,返回的操作数应包含1列错误 考虑到我在查询中需要接收的数据,是否有可能实现 第一个需要1小时的查询: SELECT c.custo

我需要从mysql数据库收集数据,以使我们能够向在给定天数内不活跃的客户发送促销电子邮件,但仅限于那些从未向我们注册过促销点的客户。该数据库相当大,拥有超过50000名客户,仅查询未注册积分的客户的客户id就需要一个多小时。 所以我想,如果我把搜索范围缩小到那些在给定时间内没有登录的客户,然后只对那些客户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)
我可以从错误消息中看出,它不允许在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)