【问题标题】:How to efficiently find frequencies in many-to-many relationships如何有效地找到多对多关系中的频率
【发布时间】:2021-04-15 03:11:45
【问题描述】:

我正在建立一个数据库来存储一个人订购某件商品的次数。 这是一个多对多的关系,但我想知道如何有效地存储客户订购某个商品的次数的频率。我唯一的选择是按语句计数和分组,还是可以重新排列我的数据库?

我的桌子现在看起来像这样:

客户表:

Customer ID Customer Name
1 Alice
2 Bob
3 Eve

物品表:

Item ID Item Name
1 Speaker
2 Keyboard
3 Mouse

购买的物品

Customer ID Item ID
1 1
1 1
1 2
1 2
2 3
2 3
3 1

所以我更感兴趣的是,客户 1 更有效地购买了 2 件商品 1、2 件商品 2 和 0 件商品 3。

【问题讨论】:

  • 什么更有效率?
  • 了解GROUP_CONCATGROUP BY
  • 您预计每个表中有多少行?

标签: mysql database database-design


【解决方案1】:

如果这与您所拥有的细节有关。您总是可以引入另一个字段来保存所购买商品的数量。如:

ALTER TABLE item_bought ADD COLUMN Count INTEGER NOT NULL;

并使用查询更新该表:

INSERT INTO item_bought (CustomerId, ItemId, Count)
VALUES (@var_customer_id, @var_item_id, @var_count)
ON DUPLICATE KEY UPDATE -- assuming CustomerId, ItemId is unique key
  Count := Count + @var_count
;

然后像这样选择它:

SELECT CustomerId, ItemId, Count
FROM item_bought
;

【讨论】:

    【解决方案2】:

    您的表格设计很好,如果您还没有添加更多信息,例如购买日期到 items_bought 表格,您可能还没有这样做。

    为了知道客户 #1 购买了您需要的商品的次数

    select i.item_id, count(ib.item_id)
    from item i
    left join items_bought ib on ib.item_id = i.item_id and ib.customer_id = 1
    group by i.item_id
    order by i.item_id;
    

    为此,您需要 items_bought 的索引。我会尝试以下两个,看看 DBMS 正在使用哪个,然后删除另一个:

    create index idx1 on items_bought (item_id, customer_id);
    create index idx2 on items_bought (customer_id, item_id);
    

    如果有一个已经包含所需数据的表会更方便。这是一种数据仓库方法。你会添加一个表

    dwh_customer_item (customer_id, item_id, amount)
    

    customer_id, item_id 上有一个主键。然后添加一个触发器,该触发器在将项目添加到数据库时添加行,添加这些行:

    insert into dwh_customer_item (customer_id, item_id, amount)
     select c.customer_id, new.item_id, 0 as amount from customer c;
    

    以及每当客户添加到数据库时添加行的触发器,添加这些行:

    insert into dwh_customer_item (customer_id, item_id, amount)
     select new.customer_id, i.item_id, 0 as amount from item i;
    

    最后一个触发器来增加每次插入 items_bought 的数量,添加这些行:

    update dwh_customer_item
    set amount = amount + 1
    where customer_id = new.customer_id
    and item_id = new.item_id;
    

    有了这样的概念,您甚至可以从 items_bought 中删除旧行而不会丢失总数。

    如果您希望将所有这些都添加到您的数据库中,这是您的选择。原始表很好,查询(提供了适当的索引)已经非常快了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-08
      • 2013-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      相关资源
      最近更新 更多