【问题标题】:Get previous X days of revenue for each group获取每个组前 X 天的收入
【发布时间】:2018-01-11 21:43:28
【问题描述】:

这是我的桌子

CREATE TABLE financials ( 
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
CountryID VARCHAR(30) NOT NULL, 
ProductID VARCHAR(30) NOT NULL,  
Revenue INT NOT NULL, 
cost INT NOT NULL, 
reg_date TIMESTAMP 
); 


INSERT INTO `financials` (`id`, `CountryID`, `ProductID`, `Revenue`, `cost`, `reg_date`) VALUES 
( 1, 'Canada', 'Doe'   , 20,  5, '2010-01-31 12:01:01'), 
( 2, 'USA'   , 'Tyson' , 40, 15, '2010-02-14 12:01:01'), 
( 3, 'France', 'Keaton', 80, 25, '2010-03-25 12:01:01'),
( 4, 'France', 'Keaton',180, 45, '2010-04-24 12:01:01'),
( 5, 'France', 'Keaton', 30,  6, '2010-04-25 12:01:01'),
( 6, 'France', 'Emma'  , 15,  2, '2010-01-24 12:01:01'),
( 7, 'France', 'Emma'  , 60, 36, '2010-01-25 12:01:01'),
( 8, 'France', 'Lammy' ,130, 26, '2010-04-25 12:01:01'),
( 9, 'France', 'Louis' ,350, 12, '2010-04-25 12:01:01'), 
(10, 'France', 'Dennis',100,200, '2010-04-25 12:01:01'),
(11, 'USA'   , 'Zooey' , 70, 16, '2010-04-25 12:01:01'),
(12, 'France', 'Alex'  ,  2, 16, '2010-04-25 12:01:01'); 

对于每个产品和日期组合,我需要获取前 5 天的收入。例如,对于产品“Keaton”,最后一次购买是在 2010 年 4 月 25 日,它只会将 2010 年 4 月 20 日至 2010 年 4 月 25 日之间的收入相加,因此它将是 210。而对于“艾玛” ,它会返回 75,因为它会将 2010-01-20 到 2010-01-25 之间的所有内容相加。

SELECT ProductID, sum(revenue), reg_date
  FROM financials f
Where reg_date in (
    SELECT reg_date
    FROM financials as t2
    WHERE t2.ProductID = f.productID
    ORDER BY reg_date
    LIMIT 5)

不幸的是,当我使用 https://sqltest.net/http://sqlfiddle.com/ 时,它说不支持“LIMIT & IN/ALL/ANY/SOME 子查询”。我的查询是否有效?

【问题讨论】:

  • 我更改了成本和收入的数据类型,因为...很明显,不是吗?无论如何,请提供所需的结果

标签: mysql sql group-by where


【解决方案1】:

您的查询在正确的轨道上,但可能无法在 MySQL 中运行。 MySQL 对 inlimit 与子查询的使用有限制。

改为:

SELECT f.ProductID, SUM(f.revenue)
FROM financials f JOIN
     (SELECT ProductId, MAX(reg_date) as max_reg_date
      FROM financials
      GROUP BY ProductId
     ) ff
     ON f.ProductId = ff.ProductId and
        f.reg_date >= ff.max_reg_date - interval 5 day
GROUP BY f.ProductId;

编辑:

如果您希望为每个产品和日期组合使用此功能,则可以使用自联接或相关子查询:

SELECT f.*,
       (SELECT SUM(f2.revenue)
        FROM financials f2
        WHERE f2.ProductId = f.ProductId AND
              f2.reg_date <= f.reg_date AND
              f2.reg_date >= f.reg_date - interval 5 day
       ) as sum_five_preceding_days
FROM financials f;

【讨论】:

  • @Strawberry 。 . .谢谢你指出这一点。我编辑了答案。
【解决方案2】:

经过一些试验,我最终得到了一些复杂的查询,我认为它可以解决您的问题

SELECT
  financials.ProductID, sum(financials.Revenue) as Revenues
FROM
  financials 
INNER JOIN (
      SELECT ProductId, GROUP_CONCAT(id ORDER BY reg_date DESC) groupedIds
      FROM financials
      group by ProductId
) group_max
  ON financials.ProductId = group_max.ProductId
     AND FIND_IN_SET(financials.id, groupedIds) BETWEEN 1 AND 5
group by financials.ProductID

首先我使用group by financials.ProductID 按产品计算收入。您面临的真正问题是为每个组消除所有不在前 5 名中的行。为此,我使用了solution from this question、GROUP_CONCAT 和 FIND_IN_SET,在没有 LIMIT 的情况下获得了前 5 个结果。我用JOIN 代替了WHERE IN,但有了这个,WHERE IN 也可以工作。

这是FIDDLE

【讨论】:

  • 我会接受你的查询,但只是出于病态的好奇,我的查询会奏效吗?
  • @eddd83 我认为你错过了一个或更多的组,除了如果它被支持将是解决这个问题的正确方法
  • @eddd83 。 . .这需要数据中的前五天,而不是截至最大日期的五个日历日。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
相关资源
最近更新 更多