SQL通过电子邮件字段获得一次客户

时间:2017-03-09 11:01:13

标签: mysql sql timeout

我有一个拥有超过100,000条记录的数据库。我试图让所有订购的客户只能按客户的电子邮件字段(OrderEmail)进行搜索。

SQL查询运行10分钟,然后超时。

如果我使用短日期范围,我可以获得结果,但仍需要3分钟。

如何优化语法以使其正常工作?

SELECT 
    tblOrders.OrderID,
    tblOrders.OrderName,
    tblOrders.OrderEmail,
    tblOrders.OrderPhone,
    tblOrders.OrderCountry,
    tblOrders.OrderDate
FROM
    tblOrders
LEFT JOIN tblOrders AS orders_join ON orders_join.OrderEmail = tblOrders.OrderEmail
    AND NOT orders_join.OrderID = tblOrders.OrderID
WHERE
    orders_join.OrderID IS NULL
    AND (tblOrders.OrderDate BETWEEN '2015-01-01' AND '2017-03-01')
    AND tblOrders.OrderDelivered = - 1
ORDER BY
    tblOrders.OrderID ASC;

2 个答案:

答案 0 :(得分:1)

我希望下面的内容能够正常运行 - 但我不能测试它,因为你没有提供样本数据。好吧,我添加了一个可用于查询的临时表定义....

但是,如果您实际上可以更改数据模型以使用INTEGER ID作为下订单的实体(而不是VARCHAR()电子邮件地址),那么您的速度会快得多。

===

正如你所看到的,它返回了Dent先生,Zaphod先生和Marvin先生,他们在示例数据中只出现过一次。

答案 1 :(得分:-1)

另一种可行的方法是,您可以按电子邮件地址分组,只获得一个条目。如果您希望获得多个订单的客户,它可能会出现不可预测的行为,但对于这种特殊情况应该没问题:

SELECT 
    tblOrders.OrderID,
    tblOrders.OrderName,
    tblOrders.OrderEmail,
    tblOrders.OrderPhone,
    tblOrders.OrderCountry,
    tblOrders.OrderDate,
    count(tblOrders.OrderID) as OrderCount
FROM
    tblOrders
WHERE
    tblOrders.OrderDate BETWEEN '2015-01-01' AND '2017-03-01'
    AND tblOrders.OrderDelivered = - 1
GROUP BY
    tblOrders.OrderEmail
HAVING
    OrderCount = 1
ORDER BY
    tblOrders.OrderID ASC;

另外,我怀疑如果你只用100k的记录看到如此长的查询时间,你可能在OrderEmail列上没有索引 - 我建议设置它,这可能有助于你的原始查询。

这在Oracle或SQL Server中不起作用,但它在MySQL和SQLite中有效。因此,虽然代码在不同的RDBMS之间不可移植,但它适用于此特定情况的