我有一个cronjob(J1),每晚计算〜1M客户的产品类别偏好。大多数客户的偏好是稳定的。但也有例外,每天都有新客户。我想通过将“diff”位设置为1来了解这些更改。然后另一个cronjob(J2)可以对这些客户执行某些操作(例如向他们发送通知)并将其设置回0。
表格如下:
CREATE TABLE customers (
customer_id VARCHAR(255),
preference VARCHAR(255),
diff TINYINT(1),
PRIMARY KEY (customer_id),
KEY (diff)
);
AFAIK,INSERT .. ON DUPLICATE KEY
不知道非关键值是否不同。所以你不能使用类似下面的东西,对吗?
INSERT customers AS ("sql for J1") ON DUPLICATE KEY
_AND_PREFERENCE_DIFFERS_ SET diff=1;
那么最好的方法是什么?
a)将表格customers
重命名为customer_yesterday
。通过运行J1创建一个新表customers
。 LEFT JOIN两个表并设置customers
的diff位。 (优点:更快?缺点:需要正确处理所有差异,例如当客户未出现在今天的输出中时)
b)循环通过J1的输出(使用python mysql连接器),customer
查询customer_id
,并仅在值不同或者是新客户时插入。 (优点:易于理解的逻辑;缺点:慢?)
有更好的解决方案吗?
更新: 正如@Barmar所问,让我们说J1的sql是一个事务分组sql,例如。
SELECT
customer_id,
GROUP_CONCAT(DISTINCT product_category SEPARATOR ',')
FROM transaction
WHERE date between _30_days_ago_ and _today_;
答案 0 :(得分:1)
为J1创建一个查询,使用LEFT JOIN
过滤掉其偏好未发生变化的客户。
INSERT INTO customers (customer_id, preference)
SELECT t1.*
FROM (
SELECT customer_id,
GROUP_CONCAT(DISTINCT product_category ORDER BY product_category SEPARATOR ',') AS preference
FROM transaction
WHERE date BETWEEN _30_days_ago_ AND _today_) AS t1
LEFT JOIN customers AS c ON t1.customer_id = c.customer_id AND t1.preference = c.preference
WHERE t1.customer_id IS NULL
ON DUPLICATE KEY UPDATE preference = VALUES(preference), diff = 1
我在ORDER BY
添加了GROUP_CONCAT
选项,以便始终按照一致的顺序返回分类。否则,当订单发生变化时,可能会导致误报。
我觉得有必要指出,在表格列中存储以逗号分隔的值通常是糟糕的数据库设计。您应该使用多对多关系表。