MySQL HABTM - 查找每个用户最连续的小部件

时间:2015-03-11 06:20:56

标签: mysql sql has-and-belongs-to-many

我目前有以下SQL数据库:

CREATE TABLE `users` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(40),
  `email` VARCHAR(40),
  PRIMARY KEY  (`id`)
);

CREATE TABLE `widgets` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `production_date` DATETIME,
  `title` VARCHAR(100),
  PRIMARY KEY  (`id`)
);

CREATE TABLE `users_widgets` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `user_id` INT(11),
  `widget_id` INT(11),
  PRIMARY KEY  (`id`)
);
ALTER TABLE `users_widgets` ADD CONSTRAINT `users_widgets_fk1` FOREIGN KEY (`user_id`) REFERENCES users(`id`);
ALTER TABLE `users_widgets` ADD CONSTRAINT `users_widgets_fk2` FOREIGN KEY (`widget_id`) REFERENCES widgets(`id`);

用户HABTM小部件。基本上,在这种情况下,我需要为每个用户确定用户付费的行中有多少小部件。小部件应该由production_date排序,以便确定它们是否是“连续的”并且每天都不会生成小部件,但是2月3d上生成的小部件和2月11日生成的小部件可以是连续的,只要没有小部件于2月4日至10日生产。

这就是网站的工作方式:网站所有者在网站上放置了许多小部件,用户可以向小部件投入资金。他们支付的金额总是1美元。一旦有足够多的用户为窗口小部件付费,就会生成窗口小部件并将一个production_date添加到窗口小部件中。

我想要实施的主要是客户忠诚度计划。用户购买了多少连续投入生产的小部件?然后,我可以为连续购买X小部件的用户提供优惠券或折扣。每个用户只能支付一次小部件,但可以支付多个小部件,一些在生产中,一些不在。未生产的窗口小部件(production_date = null)不应影响连续窗口小部件的计算。

自动增量在这里确实不起作用,因为小部件可能以与最初创建的数据库记录不同的顺序投入生产。因此,我需要通过production_date对小部件进行排序,以确定哪些小部件是连续的。

1 个答案:

答案 0 :(得分:1)

首先 - 您需要指定"付费"意味着,以及如何在表中表示。 此外,您需要阐明如何处理用户添加2个付费小部件,免费小部件以及其他2个付费小部件的情况。

在我看来,您在users_widgets表中缺少信息,因为您的小部件可以分配给许多用户,但您没有将小部件分配给的日期信息特定用户,而不是小部件是否已付款。 我建议这个表格看起来像:

CREATE TABLE `users_widgets` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `user_id` INT(11),
  `widget_id` INT(11),
  `purchase_date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  `price` decimal(10,2),
  PRIMARY KEY  (`id`)
);
  

附注:

     
      
  1. 如果您的小部件无法分配给多个用户 - 那么   没有必要将数据分成2个表(小部件和   users_widgest)。在这种情况下,只保留一张包含所有数据的表格。

  2.   
  3. 您可以信任自动增量购买活动的订单,但如果您不添加购买日期 - 它将会丢失。

  4.   
  5. 如果您的所有小工具都已付款 - 您可以跳过价格或付费字段并执行所有用户小工具的简单计数。

  6.   

如上所述,拥有users_widgets表,您应该执行以下查询:

SELECT a.user_id, sum(if(a.price is not null and b.price is not null,1,0)) 
FROM users_widgets a 
JOIN users_widgets b 
    ON a.user_id = b.user_id AND a.id<b.id 
LEFT OUTER JOIN users_widgets c 
    ON a.user_id = c.user_id AND a.id < c.id AND b.id > c.id 
WHERE c.id is null 
GROUP BY (a.user_id);
  

此查询将告诉您每个用户添加了多少连续付费小部件。   但请注意,如果用户添加了2个付费小部件,1个免费小部件,然后再添加2个付费小部件,您将收到该用户2的结果,因为在另一次购买后只有2次购买。

<强> ========== UPDATE ==========

检查这是否可以帮助您解决问题

SELECT u1.user_id, count(1) 
FROM users_widgets u1 
JOIN widgets w1 
   ON u1.widget_id=w1.id 
JOIN widgets w2 
   ON w1.production_date<w2.production_date 
JOIN users_widgets u2 
   ON w2.id=u2.widget_id 
LEFT OUTER JOIN widgets w3 
   ON w1.production_date < w3.production_date 
   AND w2.production_date>w3.production_date 
WHERE w3.id is null 
  AND u1.user_id=u2.user_id 
GROUP BY user_id;
  

请注意,在这种情况下,如果用户连续购买了2个   小部件然后错过了一个,后来又买了2个 - 你会的   该用户收到2分(每次执行1次时为1)   连续购买)

我强烈建议您不要在生产数据库中运行此类查询。