1

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

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

这代表了哪个工作人员订购、登记和收集了每个订单。

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

因此,对于 1 号工作人员(John),这将是 1 个订单、1 个签到和 1 个已取货。工作人员 2 (Simon) 将是 1 个订单、2 个签到和 0 个收款,以此类推。

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

4

3 回答 3

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子句以仅过滤上个月的行

样本输出:

| 身份证 | 姓名 | 订购 | 签到 | 收集 |
|----|-------|---------|---------|-----------|
| 1 | 约翰 | 1 | 1 | 1 |
| 2 | 西蒙 | 1 | 2 | 0 |
| 3 | 马克 | 0 | 0 | 0 |
| 4 | 海伦 | 2 | 1 | 3 |

这是SQLFiddle演示

于 2013-09-26T22:06:34.113 回答
0

彼得姆的答案是正确的。下面的代码在没有“员工”表的情况下基本相同。如彼得姆所示,使用 COALESCE。重要的是执行外部联接,而不是内部联接,因此您的报告中仍会显示 0 计数。

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;
于 2013-09-26T22:53:43.533 回答
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
于 2013-09-26T21:56:22.800 回答