使用SUM计算来自多个表的数据

时间:2011-09-24 06:12:58

标签: mysql sql sum

我有位置表

tbl_positions
   id position
    1 Driver
    2 Lobby
    3 Support
    4 Constructor 

在其他表中我有用户

编辑:

   tbl_workers
      id   name   position position2 status
       1   John   2        3         4
       2   Mike   3        2         2
       3   Kate   2        0         3
       4   Andy   1        0         0

我请求职位

SELECT p.id, 
    p.position, 
    SUM(CASE w.Status WHEN 2 THEN 1 ELSE 0 END)  AS booked,
    SUM(CASE w.Status WHEN 3 THEN 1 ELSE 0 END)  AS placed
  FROM  tbl_positions AS p LEFT JOIN tbl_workers AS w 
      ON w.position=p.id
GROUP BY p.id, p.position

我需要在单个查询中输出这样的内容。

Position    booked placed
Driver        0       0
Lobby         1       2
Support       0       2
Constructor   0       0

我需要将字段positon1和position2分开,而不是一个。我认为很容易修改它,但我找不到合适的解决方案,请帮忙。

编辑:已添加状态4

3 个答案:

答案 0 :(得分:1)

您可以加入tbl_workers而不是加入position,而position2SELECT w.id, w.name, CASE x.pos WHEN 1 THEN w.position ELSE w.position2 END AS position, w.status FROM tbl_workers AS w CROSS JOIN (SELECT 1 AS pos UNION ALL SELECT 2) AS x 位于同一列但位于不同的行中。

以下是univoting的样子:

tbl_workers

这是整个查询,基本上是您的原始查询,上面的查询替换SELECT p.id, p.position, SUM(CASE w.Status WHEN 2 THEN 1 ELSE 0 END) AS booked, SUM(CASE w.Status WHEN 3 THEN 1 ELSE 0 END) AS placed FROM tbl_positions AS p LEFT JOIN ( SELECT w.id, w.name, CASE x.pos WHEN 1 THEN w.position ELSE w.position2 END AS position, w.status FROM tbl_workers AS w CROSS JOIN (SELECT 1 AS pos UNION ALL SELECT 2) AS x ) AS w ON w.position=p.id GROUP BY p.id, p.position 表:

SELECT p.id, 
  p.position, 
  SUM(CASE w.Status WHEN 2 THEN 1 ELSE 0 END)  AS booked,
  SUM(CASE w.Status WHEN 3 THEN 1 ELSE 0 END)  AS placed
FROM tbl_positions AS p
  LEFT JOIN (
    SELECT
      w.id,
      w.name,
      CASE x.pos WHEN 1 THEN w.position ELSE w.position2 END AS position,
      CASE w.status
        WHEN 4 THEN CASE x.pos WHEN 1 THEN 3 ELSE 2 END
        ELSE w.status
      END AS status
    FROM tbl_workers AS w
      CROSS JOIN (SELECT 1 AS pos UNION ALL SELECT 2) AS x
  ) AS w 
  ON w.position=p.id
GROUP BY p.id, p.position

<强>更新

根据评论中的其他要求,这是一个经过修改的脚本:

4

我们的想法是使用32替换子选项中的position状态,具体取决于我们当前是将position2还是position拉为统一的{{1}}。外部选择保持使用与以前相同的逻辑。

答案 1 :(得分:0)

不确定“评估两个字段”是什么意思 - 但这里有一个如何总结两者的例子:

SELECT
P.ID,
P.POSITION,
((SELECT SUM (CASE W.STATUS WHEN 2 THEN 1 ELSE 0 END) FROM TBL_WORKERS W WHERE W.POSITION = P.ID) + (SELECT SUM (CASE W.STATUS WHEN 2 THEN 1 ELSE 0 END) FROM TBL_WORKERS W WHERE W.POSITION2 = P.ID)) AS BOOKED,
((SELECT SUM (CASE W.STATUS WHEN 3 THEN 1 ELSE 0 END) FROM TBL_WORKERS W WHERE W.POSITION = P.ID) + (SELECT SUM (CASE W.STATUS WHEN 3 THEN 1 ELSE 0 END) FROM TBL_WORKERS W WHERE W.POSITION2 = P.ID)) AS PLACED
FROM TBL_POSITIONS P

答案 2 :(得分:0)

因为你的数据没有规范化(即:两列都代表一行中的一个位置),我会首先对工人进行UNION,然后应用你的外部计数/组... ...内部查询的每个部分都是预聚合的,仅计算符合状态2或3的记录并具有位置。所以,如果你有一个大表,那么性能会更明显。然后,使用COALESCE()在所有可能位置的外层对该结果求和,以防止输出结果中出现NULL值。

SELECT 
      p.id,
      p.position, 
      coalesce( SUM(w.Booked), 0 )  AS booked,
      coalesce( SUM(w.Placed), 0 )  AS placed
   FROM  
      tbl_positions AS p 
         LEFT JOIN 
            ( select w1.Position as PositionID,
                     sum( if( w1.status = 2, 1, 0 )) as Booked,
                     sum( if( w1.status = 3, 1, 0 )) as Placed
                 from 
                     tbl_workers w1
                 where
                         w1.status in ( 2, 3 )
                     and w1.Position > 0
                 group by 
                     PositionID
              union all
              select w2.Position2 as PositionID,
                     sum( if( w2.status = 2, 1, 0 )) as Booked,
                     sum( if( w2.status = 3, 1, 0 )) as Placed
                 from
                     tbl_workers w2
                 where
                         w2.status in ( 2, 3 )
                     and w2.Position2 > 0
                 group by 
                     PositionID ) as w
        on p.id = w.positionID
   group by
       p.id,
       p.position