2017-05-24 172 views
1

我有一个查询可以为我们的客户生成损益表,但我在加入订单表时遇到问题,导致SUM乘以费用分录数量。MySQL查询:SUM计数重复行

我有以下表格:

  • user_report_categories, “URC”,这是类的标题对于谁报告
  • user_report_expenses, “茜”,这是个人的开支,以 “adjusted_cost” 用户和一个“费用日期”。这些可能会或可能不会有与它们相关的订单,但在这种情况下,我们只关心与订单相关的费用。每个订单可能有多个开支,但每个开支/订单将始终处于不同的类别。
  • 订单,“O”,它有一个“agreed_fee”,“平衡”,当然,一个“id”

报告需要用户选择的日期范围内具有每月一列,用单元格中的计算值。

查询原样如下:

SELECT 
SUBSTRING(MONTHNAME(STR_TO_DATE(m, '%m')), 1, 3) AS month, 
COUNT(o.id) AS "# of Orders", 
ROUND(SUM(o.agreed_fee) - SUM(o.balance), 2) AS "Total Income", 
ROUND(SUM(ure.adjusted_cost), 2) AS "Total Expenses", 
ROUND(SUM(o.agreed_fee) - SUM(o.balance) - SUM(ure.adjusted_cost), 2) AS "Profit & Loss", 
"" AS "", 
ROUND(SUM(ure.adjusted_cost)/COUNT(ure.id), 2) AS "% of Expenses per Order", 
ROUND((SUM(o.agreed_fee) - SUM(o.balance))/COUNT(ure.id), 2) AS "Average Fee per Order", 
ROUND(((SUM(o.agreed_fee) - SUM(o.balance))/COUNT(ure.id)) - (SUM(ure.adjusted_cost)/COUNT(ure.id)), 2) AS "Average P/L per Order" 

FROM ( 
    SELECT y, m FROM 
    (SELECT YEAR('2016-01-01') y) years, 
    (SELECT 1 m UNION ALL SELECT 2 UNION ALL SELECT 3) months 
) ym 

LEFT JOIN user_report_categories AS urc ON urc.user_id = 48 
LEFT JOIN user_report_entries AS ure ON ure.user_category_id = urc.id AND YEAR(ure.expense_date) = y AND MONTH(ure.expense_date) = m 
LEFT JOIN orders AS o ON o.id = ure.order_id 
WHERE urc.report_type = 'expense' AND urc.user_id = 48 AND ure.order_id IS NOT NULL 
GROUP BY y, m 

和结果:

month,# of Orders,Total Income,Total Expenses,Profit & Loss,,% of Expenses per Order,Average Fee per Order,Average P/L per Order 
Jan,387,36400.00,5921.17,30478.83,,15.30,94.06,78.76 
Feb,559,55327.50,8165.12,47162.38,,14.61,98.98,84.37 
Mar,736,74785.00,10261.07,64523.93,,13.94,101.61,87.67 

我确定通过将订单ID的组由该订单被乘以的支出数

GROUP BY y, m, o.id 

并查看每行有多个订单的新结果:

month,# of Orders,Total Income,Total Expenses,Profit & Loss,,% of Expenses per Order,Average Fee per Order,Average P/L per Order 
Jan,6,360.00,31.95,328.05,,5.33,60.00,54.68 
Jan,1,0.00,30.24,-30.24,,30.24,0.00,-30.24 
Jan,6,1200.00,141.74,1058.26,,23.62,200.00,176.38 
Jan,6,540.00,160.97,379.03,,26.83,90.00,63.17 
Jan,6,540.00,98.77,441.23,,16.46,90.00,73.54 
Jan,8,720.00,167.44,552.56,,20.93,90.00,69.07 
... etc ... 

或者,当我从组通过删除o.id,而是改变订单行#数不同:

COUNT(DISTINCT o.id) AS "# of Orders", 

我得到正确的价值观为订单#,但当然由于重复,SUM顺序表值的其他值仍然不正确。

month,# of Orders,Total Income,Total Expenses,Profit & Loss,,% of Expenses per Order,Average Fee per Order,Average P/L per Order 
Jan,71,36400.00,5921.17,30478.83,,15.30,94.06,78.76 
Feb,105,55327.50,8165.12,47162.38,,14.61,98.98,84.37 
Mar,146,74785.00,10261.07,64523.93,,13.94,101.61,87.67 

我不知道如果我即使考虑一个好方法这一点,但在一个查询中这样做产生是一个巨大的优势,对我来说,所以我试图拼凑一起。我怎样才能得到它在不同的订单ID的SUM订单表值,否则更正查询以正确计算?谢谢!


回答

@Sal踢我了,我有结束最后的查询如下。我认为它也涵盖了评论中出现的所有问题。

SELECT 
SUBSTRING(MONTHNAME(STR_TO_DATE(m, '%m')), 1, 3) AS month, 
orders AS "# of Orders", 
round(total_income,2) AS "Total Income", 
round(total_expenses,2) AS "Total Expenses", 
round(total_income-total_expenses,2) AS "Profit & Loss", 
"" AS "", 
round(total_expenses/orders,2) AS "% of Expenses per Order", 
round(total_income/orders,2) AS "Average Fee per Order", 
round((total_income/orders)-(total_expenses/orders), 2) AS "Average P/L per Order" 

     FROM ( 
      SELECT m, 
      (SELECT count(o.id) 
       FROM orders o 
       WHERE year(o.datetime) = ym.y 
       AND month(o.datetime) = ym.m AND o.user_id = 48 
       AND o.cancelled = 0 
      ) AS orders, 
      (SELECT IFNULL(sum(o.agreed_fee - o.balance), 0) 
       FROM orders AS o 
       WHERE year(o.datetime) = ym.y 
       AND month(o.datetime) = ym.m 
       AND o.user_id = 48 
       AND o.cancelled = 0 
      ) AS total_income, 
      (SELECT IFNULL(sum(ure.adjusted_cost),0) 
       FROM user_report_entries AS ure 
       INNER JOIN user_report_categories AS urc ON urc.id = ure.user_category_id 
        WHERE year(ure.expense_date) = ym.y 
       AND month(ure.expense_date) = ym.m 
       AND urc.user_id = 48 AND urc.id NOT IN (6287)) AS total_expenses 
      FROM (SELECT 2017 y, 1 m UNION SELECT 2017, 2 UNION SELECT 2017, 3 
      ) ym 

      GROUP BY y, m 
     ) t 
+0

'COUNT(o.id)'和'GROUP BY','COUNT(o.id)''没有GROUP BY'和'COUNT (DISTINCT)'互不相同,并且会返回不同的值。根据上面的查询,理解预期的输出是不容易的,因此添加更多信息(即表格模式和/或输出)或者只是一个[SQLFiddle](http://sqlfiddle.com/)。 –

+0

我感觉到一个问题:'user_report_entries'有成本并且与订单有关。假设您的订单中的“约定的费用”为100.对于此订单,您有一个2016-01的报告条目,其中“adjusted_cost”为40,另一个报告条目为2016-02,“adjusted_cost”为50.所以你计算两个月中的哪一个与'agree_fee'?您需要一个算法(可能仅在第一次或最后一次报告的月份或订单日期的月份计算订单及其所有报告条目)。 –

+0

@DarshanMehta这些是我尝试过的一些事情和他们的结果。我需要查询的行为方式是每个订单只计算一次,即使每个订单有多个费用。 – Lea

回答

1

我希望对您有所帮助:

SELECT substring(monthname(str_to_date(m,'%m'), 1, 3) month 
    , orders "# of Orders" 
    , round(total_income,2) "Total Income" 
    , round(total_expenses,2) "Total Expenses" 
    , round(total_income-total_expenses,2) "Profit & Loss" 
    , round(total_expenses/orders,2) "% of Expenses per Order" 
    , round(total_income/orders,2) "Average Fee per Order" 
    , round((total_income/orders)-(total_expenses/orders), 2) "Average P/L per Order" 
    FROM (SELECT m 
       , (SELECT count(distinct ure.order_id) 
        FROM user_report_entries ure 
        WHERE year(ure.expense_date) = ym.y 
         AND month(ure.expense_date) = ym.m 
       ) orders 
       , (SELECT sum(o.agreed_fee - o.balance) 
        FROM user_report_entries ure 
         INNER JOIN orders o 
         ON o.id = ure.order_id    
        WHERE year(ure.expense_date) = ym.y 
         AND month(ure.expense_date) = ym.m 
       ) total_income 
       , sum(ure.adjusted_cost) total_expenses 
      FROM (SELECT 2016 y, 1 m 
        UNION 
        SELECT 2016, 2 
        UNION 
        SELECT 2016, 3 
       ) ym 
      LEFT JOIN user_report_entries ure 
       ON year(ure.expense_date) = ym.y 
       AND month(ure.expense_date) = ym.m 
      LEFT JOIN user_report_categories urc 
       ON urc.id = ure.user_category_id 
      WHERE urc.user_id = 48 
      AND urc.report_type = 'expense' 
      GROUP BY y, m 
     ) t 
+0

这会把我踢向正确的方向,我调整了一下,现在就开始工作了,谢谢! – Lea