MySQL:在重复键上插入不同的值时设置“diff”位?

时间:2015-07-04 05:16:37

标签: python mysql

我有一个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_;

1 个答案:

答案 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选项,以便始终按照一致的顺序返回分类。否则,当订单发生变化时,可能会导致误报。

我觉得有必要指出,在表格列中存储以逗号分隔的值通常是糟糕的数据库设计。您应该使用多对多关系表。