优化相关表中复杂的总和和计数

Ped*_*o A 1 mysql performance join count php query-performance

我有一个categories表,它有两列,idname.

我有一个types表,其中包含三列idcategory_idpoints

我有一个products表,其中包含三列idtype_idcustomer_id

这意味着每个产品都有一个类型,每个类型都有一个类别。一个品类有多种类型,一种类型有多种产品。

我正在使用 MySQL 和 PHP。

从 PHP 中,给定customer_id,我想知道客户在每个类别中分别拥有多少分(例如,向用户显示一个表格)。

我的解决方案:我首先会做一个查询来查找所有类别 id,然后对于每个category_id我会找到该类别中的所有类型(即,所有具有给定 的类型category_id);然后对于每一个,type_id我会计算有多少产品同时具有那个type_id和给定的customer_id,我会把那个数量乘以给定的点数type_id。将每个结果的所有结果相加type_id,我最终得到了给定客户在这方面的总分category_id。正如我所说,我必须为每个category_id. 我的解决方案会起作用,但在我看来它会非常慢。我正在寻找有关如何以更好的方式解决此问题的建议 - 使用更少的查询,或更快的查询,或两者兼而有之。 按照现在的方式,它可能会执行与类别数量一样多的查询。


例子:

/* TABLE: categories */

name           id
A              1
B              2
C              3

/* TABLE: types */

points         id          category_id
1000             1                1
500              2                1
200              3                3
50               4                2
20               5                3
1                6                3

/* TABLE: products */

id           type_id          customer_id
1               2                   13
2               4                   13
3               5                   13
4               6                   13
5               5                   13
6               3                   13
7               4                   13
8               5                   13
9               6                   13
Run Code Online (Sandbox Code Playgroud)

如果给定的 customer_id 是 13,我想得到如下内容:

A类总分500分 B类总分100分 C类总分262分

1. 在不改变我的数据库结构的情况下,有什么好的方法可以做到这一点?

2. 有没有好的方法可以更改我的数据库设计以允许更好的方法来做到这一点?(当然,为了简单起见,我省略了表格中的其他字段)。

Han*_*non 5

您的问题表明您正在以程序方式思考,但是您需要以“基于集合”的方式思考。

以下查询可以帮助您更好地理解这一点:

SELECT p.customer_id
    , c.name
    , sum(t.points)
FROM products p
    INNER JOIN types t ON p.type_id = t.id
    INNER JOIN categories c ON t.category_id = c.id
GROUP BY p.customer_id
    , c.name;
Run Code Online (Sandbox Code Playgroud)

本质上,这应该向您显示 customer_id、类别名称以及每个客户在每个类别中的总积分的列表。它通过使用聚合函数 ( SUM) 和GROUP BY子句来实现这一点。

(有关命名列的信息,请在此处查看我的回答ID