订单表中有多个mysql计数

时间:2013-09-26 21:48:25

标签: mysql sql

我有一个如下所示的订单表

order_id  ordered    checkin    collected   
======================================
1           2           1           4       
2           4           2           4       
3           4           2           4       
4           1           4           1      

这表示哪位员工订购,签入并收集了每个订单。

我想执行一个SQL查询,该查询计算每个员工的订单,签到和收集的数量。这也将加入到工作人员表中,该表输出每行的工作人员姓名

因此,对于工作人员1(约翰)来说,这将是1个订单,1个签入和1个收集。 工作人员2(西蒙)将是1个订单,2个签到和0个收集,等等其他工作人员。

实现这一目标的最佳mysql查询是什么?

3 个答案:

答案 0 :(得分:1)

更新:您可以单独计算每列的每个员工ID的行数,然后使用外部联接与员工表联系。

SELECT s.id, s.name, 
       COALESCE(o.ordered,   0) ordered, 
       COALESCE(c.checkin,   0) checkin, 
       COALESCE(l.collected, 0) collected
  FROM staff s LEFT JOIN 
(
  SELECT ordered id, COUNT(*) ordered
    FROM orders
-- WHERE ordered_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
--   AND ordered_date <= LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
   GROUP BY ordered
) o ON s.id = o.id LEFT JOIN
(
  SELECT checkin id, COUNT(*) checkin
    FROM orders
-- WHERE checkin_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
--   AND checkin_date <= LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
   GROUP BY checkin
) c ON s.id = c.id LEFT JOIN
(
  SELECT collected id, COUNT(*) collected
    FROM orders
-- WHERE collected_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
--   AND collected_date <= LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
   GROUP BY collected
) l ON s.id = l.id

或者您可以采用不同的方法首先取消orders表格,然后按员工ID有条件地汇总它,然后再使用外部联接将其与员工表连接

SELECT s.id, s.name,
       COALESCE(p.ordered,   0) ordered, 
       COALESCE(p.checkin,   0) checkin, 
       COALESCE(p.collected, 0) collected
  FROM staff s LEFT JOIN
(
  SELECT id, 
         SUM(type = 1) ordered,
         SUM(type = 2) checkin,
         SUM(type = 3) collected
    FROM
  (
    SELECT type,
           CASE type 
             WHEN 1 THEN ordered 
             WHEN 2 THEN checkin
             WHEN 3 THEN collected
           END id
      FROM orders CROSS JOIN
    (
      SELECT 1 type UNION ALL
      SELECT 2 UNION ALL
      SELECT 3
    ) n
--   WHERE (ordered_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
--     AND  ordered_date <= LAST_DAY(CURDATE() - INTERVAL 1 MONTH)) 
--      OR (checkin_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
--     AND  checkin_date <= LAST_DAY(CURDATE() - INTERVAL 1 MONTH))
--      OR (collected_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
--     AND  collected_date <= LAST_DAY(CURDATE() - INTERVAL 1 MONTH))
  ) u
   GROUP BY id
) p
    ON s.id = p.id

根据您的评论,已使用示例WHERE子句更新了查询,以仅过滤上个月的行

示例输出:

| ID |  NAME | ORDERED | CHECKIN | COLLECTED |
|----|-------|---------|---------|-----------|
|  1 |  John |       1 |       1 |         1 |
|  2 | Simon |       1 |       2 |         0 |
|  3 |  Mark |       0 |       0 |         0 |
|  4 | Helen |       2 |       1 |         3 |

这是 SQLFiddle 演示

答案 1 :(得分:0)

您可以使用COUNT(*)计算表格中的所有订单。同时使用COUNT(checkin) COUNT(collected)计算其他字段。

如果您尝试获取一个用户的计数,可以使用WHERE来执行此操作。

SELECT
  COUNT(order_id) AS   order_count,
  COUNT(checking) AS chcekin_count,
  COUNT(collected) AS collected_count
FROM
  your table
  WHERE staff_member = idOfStaff

您还可以从表中执行许多计数并将其作为一个表收集

SELECT
  (SELECT COUNT(order_id) FROM table WHERE staff = ?)   AS staff_1_order_count,
  (SELECT COUNT(order_id) FROM table WHERE staff = ?)   AS staff_2_order_count

答案 2 :(得分:0)

peterm的回答是正确的。如果没有“员工”表,下面的代码基本相同。正如peterm所示,使用COALESCE。重要的一点是进行外连接,而不是内部连接,因此计数仍会显示在报表中。

select T1.member,T1.ordered_count,T2.checkin_count, collected_count
from (
    select ordered as "member", count(*) as "ordered_count"
    from orders group by ordered
) as T1
left join  (
    select checkin as "member", count(*) as "checkin_count"
    from orders
    group by checkin
) as T2 on T1.member=T2.member
left join  (
    select collected as "member", count(*) as "collected_count"
    from orders
    group by collected
) as T3 on T2.member=T3.member;