好的,我有一张表格,其中包含与日期和持续时间相关的付款。
示例数据:
purchase_id date_purchased user_id duration (in months) amount_income
1 2013-12-28 00:00:00 1 2 £15
2 2014-01-04 00:00:00 2 1 £10
3 2014-02-04 00:00:00 3 6 £40
*因此,用户支付的时间越长,他们每月支付的费用就越少。
我想要显示的是基于此表的每月总收入。因此,2个月内支付15英镑将意味着每月收入7.50英镑,为期2个月。
示例输出:
Month Amount
2013-12 £7.50
2014-01 £17.50
2014-02 £6.66
2014-03 £6.66
2014-04 £6.66
2014-05 £6.66
2014-06 £6.66
2014-07 £6.66
此输出对应于上面的示例输入。希望它能澄清每月收入的细分。
如何在查询中执行此操作?
答案 0 :(得分:0)
根据假设您可以轻松地从日期时间中提取月份,因此真正的问题是关于聚合逻辑,并且您可以创建数字表。
这是一个显示模式的简单示例。
CREATE TABLE Num (num int);
INSERT INTO Num VALUES (0),(1),(2),(3),(4);
CREATE TABLE Tbl (start int, run int);
INSERT INTO Tbl VALUES (1,2),(2,3);
SELECT start + num active_month
,count(*) * 10 income
FROM Tbl
INNER JOIN
Num ON num < run
GROUP BY start + num
答案 1 :(得分:0)
怎么样:
SELECT a.my_date, a.income, IFNULL(SUM(DISTINCT(a.income)) + sum( b.income ), a.income) as roll_up
FROM (
SELECT purchase_id, DATE_FORMAT( date_purchased, '%y-%m') AS my_date, SUM( amount_income / duration ) AS "income"
FROM incomes
GROUP BY my_date
) AS a
LEFT OUTER JOIN (
SELECT purchase_id, DATE_FORMAT( date_purchased, '%y-%m') AS my_date, SUM(amount_income / duration ) AS "income"
FROM incomes
GROUP BY my_date
) AS b ON ( a.purchase_id > b.purchase_id )
GROUP BY a.purchase_id
一次性完成这项工作有点棘手 - 而且可能会有所改进 - 但这会产生以下结果:
my_date income roll_up
13-12 8.5000 8.5000
14-01 10.0000 18.5000
14-02 16.6667 35.1667
我的数据集是:
1 2013-12-28 00:00:00 1 2 15
2 2014-01-04 00:00:00 2 1 10
3 2014-02-04 00:00:00 3 6 40
4 2013-12-29 00:00:00 4 1 1
5 2014-02-28 00:00:00 5 2 20
答案 2 :(得分:0)
SELECT
时,它只是看起来像这样:
n
---
0
1
2
3
…
通过它你可以构建一个这样的查询:
SELECT
purchases.purchase_id,
purchases.date_purchased,
purchases.duration,
-- generator_16 is our numbers table
generator_16.n,
-- Below we calculate the year and month (year_mon) in the following way:
-- (1) Get the first day of the year, e.g. if date_purchased is 2012-12-28,
-- this gives us 2012-01-01.
-- (2) Get the month number, e.g. 12 for 2012-12-28) and add that many months
-- to the first day of the year, which gives us the first day of the
-- month, 2012-12-01.
-- (3) Add "n" months, where "n" is the number we get from the numbers table,
-- starting at 0.
DATE_ADD( -- (3)
DATE_ADD( -- (2)
MAKEDATE( YEAR(purchases.date_purchased), 1 ), -- (1)
INTERVAL MONTH(purchases.date_purchased) - 1 MONTH -- (2)
),
INTERVAL generator_16.n MONTH -- (3)
) AS year_mon,
purchases.amount_income / purchases.duration AS amount
FROM purchases
-- The below JOIN means that if `purchases.duration` is 3, we get three rows
-- that have 0, 1, and 2 in the `n` column, which we use as the number of dates
-- to add in (3) above.
JOIN generator_16
ON generator_16.n BETWEEN 0 AND purchases.duration - 1
ORDER BY purchases.purchase_id, year_mon;
这给了我们这样的结果(SQL Fiddle):
purchase_id date_purchased duration n year_mon amount
----------- -------------- -------- - ------------ ------
1 2013-12-28 … 2 0 2013-12-01 … 7.5
1 2013-12-28 … 2 1 2014-01-01 … 7.5
2 2014-01-04 … 1 0 2014-01-01 … 10
3 2014-02-04 … 6 0 2014-02-01 … 6.6667
3 2014-02-04 … 6 1 2014-03-01 … 6.6667
3 2014-02-04 … 6 2 2014-04-01 … 6.6667
3 2014-02-04 … 6 3 2014-05-01 … 6.6667
3 2014-02-04 … 6 4 2014-06-01 … 6.6667
3 2014-02-04 … 6 5 2014-07-01 … 6.6667
我插入空行以分隔purchase_id
群组,以便您了解群组中每个项目的n
从0
增加到duration - 1
的方式。如您所见,year_mon
等于n
个月加date_purchased
个月的第一天n
个月后,amount
等于{amount_income / duration
1}}。
我们差不多完成了,但是你可以看到year_mon
有重复:2014-01-01
会显示两次。这是一个好消息,因为我们可以使用GROUP BY
按该列进行分组,然后使用SUM(amount)
获取该月的总数:
SELECT
DATE_ADD(
DATE_ADD(
MAKEDATE( YEAR(purchases.date_purchased), 1 ),
INTERVAL MONTH(purchases.date_purchased) - 1 MONTH
),
INTERVAL generator_16.n MONTH
) AS year_mon,
SUM(purchases.amount_income / purchases.duration) AS total
FROM purchases
JOIN generator_16
ON generator_16.n BETWEEN 0 AND purchases.duration - 1
GROUP BY year_mon
ORDER BY year_mon;
此查询与上个月之间的唯一区别是,我们会GROUP BY year_mon
然后SUM(amount_income / duration)
获取该月的total
,从而产生此结果(SQL Fiddle) :
year_mon total
------------ ------
2013-12-01 … 7.5
2014-01-01 … 17.5
2014-02-01 … 6.6667
2014-03-01 … 6.6667
2014-04-01 … 6.6667
2014-05-01 … 6.6667
2014-06-01 … 6.6667
2014-07-01 … 6.6667
...当然,您可以使用DATE_FORMAT
和CAST
或ROUND
来获取格式正确的日期和金额,或者您可以在前端代码中执行此操作。