1

我在mysql中有以下表格:

钱:

用户名,日期,金额

花费:

用户名,日期,金额

我需要一个 sql 语句(报告),每周总计(存款 - 用户使用的金额),并按用户、周分组

这是我到目前为止所拥有的:

SELECT   expenses.userid      AS user,
         MONTH(expenses.date) AS month,
         SUM(money.amount)    AS amount_money,
         SUM(expenses.amount) AS expenses_amount
FROM     expenses INNER JOIN money ON money.userid = expenses.userid
GROUP BY 1,2 WITH ROLLUP

(星期一是一周的第一天)

样本数据:

钱:

2012-11-05 abustos 70000

2012-11-05 psepulveda 35000

2012-10-07 fmonsalves 45000

2012-09-07 阿布斯托斯 55000

2012-09-07 abustos 50000

2012-08-09 abustos 100000

2012-08-21 csuarez 130000

2012-08-09 fmonsalves 100000

花费:

2012-05-24    csuarez     30000

2012-08-29    csuarez     30000

2012-08-22    csuarez     7990

2012-08-22    csuarez     21220

2012-08-23    csuarez     45577

我想要这样的东西:

用户: csuarez

周:2012 年 8 月 19 日 2012 年 8 月 25 日

金钱:130000

费用:115898

谢谢你的帮助!

4

2 回答 2

1

请试试这个:

SELECT money.userid as user, 
yearweek(expenses.date) as `week`, 
sum(money.amount) as amount_money, 
sum(expenses.amount) as expenses_amount,
sum(money.amount - expenses.amount) as deposit 
FROM money
LEFT JOIN expense
ON money.userid = expenses.userid 
group by `week`, money.userid;

根据 eggyal 的评论,您可以modeweek函数内使用来获得一周的第一个星期一。 参考

SELECT money.userid as user, 
week(expenses.date, 1) as `week`, 
sum(distinct money.amount) as amount_money, 
sum(distinct expenses.amount) as expenses_amount,
sum(money.amount - expenses.amount) as deposit 
FROM money 
LEFT JOIN expense
ON money.userid = expenses.userid 
group by `week`, money.userid;

在 op 给出样本数据后的后期更新:

于 2013-01-14T15:09:00.170 回答
1

要导出星期一“开始”一周的日期(从星期一到星期日的星期),您可以使用如下表达式:

mydate + INTERVAL IF(DAYOFWEEK(mydate)-1,2-DAYOFWEEK(mydate),-6) DAY 
  AS starting_monday

同样,要导出一周中“结束”星期日的日期值:

mydate + INTERVAL IF(DAYOFWEEK(mydate)-1,8-DAYOFWEEK(mydate),0) DAY 
  AS ending_sunday

但这并不是查询的真正问题,假设您的表money代表对帐户的存款(而不是余额),并且您的expenses表代表从帐户中提款。

用户可能会有一周的取款但没有存款,或者一周有存款但没有取款。对两个表使用 JOIN 操作的查询可能会排除行。而 OUTER JOIN 只解决了一半的问题。

根据您的描述,听起来您确实想要一个包含本周所有提款和所有存款的查询。

一种方法是使用 UNION ALL 操作组合来自两个单独表的行:

SELECT 'm' AS m_or_e
     , m.userid
     , m.date
     , m.amount
  FROM money
 UNION ALL
SELECT 'e'
     , e.userid
     , e.date
     , -1.00*e.amount AS amount
  FROM expenses

然后,您可以将该查询作为内联视图引用;但是对于大型集合,由于创建了中间(派生)表,这将表现出有问题的性能。

这不太理想:

SELECT t.userid
     , t.week_
     , SUM(t.amount) AS total
     , SUM(IF(t.source='m',t.amount,0)) AS amount_money
     , SUM(IF(t.source='e',t.amount,0)) AS expenses_amount
  FROM (
         SELECT 'm' AS source
              , m.userid
              , YEARWEEK(m.date,1) AS week_
              , SUM(m.amount) AS amount
           FROM money m
          GROUP BY m.userid, week_
          UNION ALL
         SELECT 'e' AS source
              , e.userid
              , YEARWEEK(e.date,1) AS week_
              , -1.00*SUM(e.amount)
           FROM expenses e
          GROUP BY e.userid, week_
        ) t
 GROUP BY t.userid, t.week_

对于这样的查询,理想情况下,“存款”和“取款”将记录在同一个表中,存款和取款存储为正数和负数,或区分“金钱”和“费用”的标识符。

我也没有在任何一个表上看到主键或唯一键,但添加唯一约束userid,date甚至userid,date,amount可能是有问题的。

于 2013-01-14T17:19:50.940 回答