【问题标题】:Get sold products within date range and order them by sold quantity获取日期范围内的已售产品并按已售数量订购
【发布时间】:2021-04-13 22:50:33
【问题描述】:

我有这个表格方案(删除了不重要的列):

我正在为此编写 REST API。我需要在某个日期范围内销售分页产品。

这对我来说不是问题,但我还需要按产品代码或销售数量对它们进行排序。后者对我来说是个问题。


我的想法是查询产品,然后使用子查询来查找按日期过滤的sold_products 并将结果销售数量相加。然后按那个总和排序。

这行得通,但这确实效率不高。对于每一个产品,我必须总结它的销售产品,最后我只得到 10 个结果(因为我使用的是分页)。我最近一次使用这种方式的尝试耗时 6.5 秒,所以......


我的第二个想法是从另一边走。查询 sold_products,按 product_id 分组,过滤它们,然后找到它的父母。

这很好用,就是这样,但有一个问题 - 我没有得到尚未售出的产品。


我该怎么做?我想我不需要确切的查询,只要知道我应该如何处理就足够了。

提前谢谢你!

编辑:

以 CSV 格式输入数据(希望可以这样):

产品:

id code
1 A11
2 A12
3 B11

product_variant:

id product_id code initial_quantity
1 1 A11-1 50
2 1 A11-2 50
3 1 A11-3 80
4 2 A12-1 20
5 2 A12-2 30
6 2 A12-3 80
7 2 A12-4 90
8 3 B11-1 70
9 3 B11-2 70

已售产品:

id product_id product_variant quantity date
1 1 1 20 2021-04-01
2 1 1 15 2021-04-01
3 1 2 15 2021-04-04
4 1 3 10 2021-04-05
5 1 3 19 2021-04-07
6 2 4 11 2021-04-07
7 2 5 12 2021-04-08
8 2 7 15 2021-04-10
9 2 7 15 2021-04-10

结果:

product_id product_code initial_quantity sold_quantity
1 A11 180 79
2 A12 220 53
3 B11 140 0 or NULL

销售日期范围 2021-04-07 到 2021-04-08 并按 sold_quantity asc 排序时的结果:

product_id product_code initial_quantity sold_quantity
3 B11 140 0 or NULL
1 A11 180 19
2 A12 220 23

示例数据 SQL:

CREATE TABLE product(id INT, code VARCHAR(25));
CREATE TABLE product_variant(id INT, product_id INT, code VARCHAR(25), initial_quantity INT);
CREATE TABLE sold_product(id INT, product_id INT, product_variant_id INT, quantity INT, date_time DATETIME);

INSERT INTO product VALUES(1,'A11');
INSERT INTO product VALUES(2,'A12');
INSERT INTO product VALUES(3,'B11');

INSERT INTO product_variant VALUES(1,1,'A11-1',50);
INSERT INTO product_variant VALUES(2,1,'A11-2',50);
INSERT INTO product_variant VALUES(3,1,'A11-3',80);
INSERT INTO product_variant VALUES(4,2,'A12-1',20);
INSERT INTO product_variant VALUES(5,2,'A12-2',30);
INSERT INTO product_variant VALUES(6,2,'A12-3',80);
INSERT INTO product_variant VALUES(7,2,'A12-4',90);
INSERT INTO product_variant VALUES(8,3,'B11-1',70);
INSERT INTO product_variant VALUES(9,3,'B11-2',70);

INSERT INTO sold_product VALUES(1,1,1,20,'2021-04-01');
INSERT INTO sold_product VALUES(2,1,1,15,'2021-04-01');
INSERT INTO sold_product VALUES(3,1,2,15,'2021-04-04');
INSERT INTO sold_product VALUES(4,1,3,10,'2021-04-05');
INSERT INTO sold_product VALUES(5,1,3,19,'2021-04-07');
INSERT INTO sold_product VALUES(6,2,4,11,'2021-04-07');
INSERT INTO sold_product VALUES(7,2,5,12,'2021-04-08');
INSERT INTO sold_product VALUES(8,2,7,15,'2021-04-10');
INSERT INTO sold_product VALUES(9,2,7,15,'2021-04-10');

第一个想法:

SELECT p.id, p.code,
    (
        SELECT SUM(v.initial_quantity)
        FROM product_variant AS v
        WHERE p.id = v.product_id
    ) AS initial_quantity,
    (
        SELECT SUM(s.quantity)
        FROM sold_product AS s
        WHERE p.id = s.product_id
    ) AS sold_quantity
FROM product AS p
ORDER BY sold_quantity;

第二个想法:

SELECT p.id, p.code,
    (
        SELECT SUM(v.initial_quantity)
        FROM product_variant AS v
        WHERE p.id = v.product_id
    ) AS initial_quantity,
    SUM(s.quantity) AS sold_quantity
FROM sold_product AS s
INNER JOIN product AS p ON s.product_id = p.id
GROUP BY p.code, p.id,
    (
        SELECT SUM(v.initial_quantity)
        FROM product_variant AS v
        WHERE p.id = v.product_id
    )
ORDER BY sold_quantity;

编辑:JOIN 尝试,返回单个结果以及所有已售数量的总和

SELECT p.id, p.code,
    (
        SELECT SUM(v.initial_quantity)
        FROM product_variant AS v
        WHERE p.id = v.product_id
    ) AS initial_quantity,
    SUM(s.quantity) AS sold_quantity
FROM product AS p
JOIN sold_product AS s ON p.id = s.product_id
ORDER BY sold_quantity;

【问题讨论】:

  • 实际上,我打算在那里提出与您的第一个想法类似的建议。我读到你对那个有问题.. 两个问题,对吗?一个是“最后我只取10个结果(因为我使用分页)”,另一个是关于性能。我不太了解第一个问题,我想对于第二个问题,为了提高性能,您可以尝试将 SELECT 中的子查询转换为 JOIN 并比较性能......当然还有正确的索引,它会运行得更快
  • 有多少种不同的product_id?
  • 我刚刚在生产数据库上尝试过,我写的查询花了 18.5 秒。当我删除 sold_quantity 子查询时,只用了 0.08 秒。
  • product 中有近 4 000 行,但在生产中我也有类似“全局过滤器”(WHERE product.catalog = 1),这将其缩小到 600 条记录。 sold_product 中有近 20 000 行,但并非所有这些都与我的 600 条产品记录相关联。
  • 我忘了回答:“我只取 10 个结果”并不是一个问题,我只是说我需要对所有行进行那些昂贵的计算才能得到 10 个他们。但我仍然需要做一些,以便我可以按已售出排序。而且我还尝试用 JOIN 替换子查询,但它对我不起作用。它返回所有已售数量的单个结果总和。也许我做错了,我的尝试更新了问题。

标签: mysql sql


【解决方案1】:

已解决 - sold_product.product_id 上缺少索引键。我从没想过缺少索引键会使查询速度变慢那么多,最多 30 秒。使用该索引键需要 0.1 秒。

感谢所有试图提供帮助的人!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多