SQL SUM操作多个子查询

时间:2013-08-13 05:52:15

标签: mysql sql database

我设计了以下mysql数据库表,

ticket(id, code, cust_name);
passenger(id, ticket_id, name, age, gender, fare);
service(id, passenger_id, item, cost);

一张票可以有很多乘客,每位乘客可以购买多种服务。我想要的是得到每张票的总成本。

我试过以下的sql,

SELECT 
    SUM(fare) as total_fare,
    (SELECT SUM(cost) as total_cost FROM services WHERE passenger.id = services.passenger_id) as total_service_cost
FROM
    ticket
JOIN passenger ON passenger.ticket_id = ticket.id

虽然,结果是乘客票价总额为总票价但是对于服务费用,它只汇总并返还第一位乘客的总服务费用。

我认为我需要更多的查询嵌套,需要帮助,如果可能的话,我怎么能得到结果总计为乘客票价和服务成本总计。

好的,这里是sql insert statment来澄清,


INSERT INTO `ticket` (`id`, `code`, `cust_name`) VALUES
(1, 'TK01', 'Dipendra Gurung');

INSERT INTO `passenger` (`id`, `ticket_id`, `name`, `age`, `gender`, `fare`) VALUES
(1, 1, 'John', '28', 'M', 120),
(2, 1, 'Kelly', '25', 'F', 120);

INSERT INTO `services` (`id`, `passenger_id`, `item`, `cost`) VALUES
(1, 1, 'S1', 30),
(2, 1, 'S2', 50),
(3, 2, 'S3', 50);

我想获得机票'TK01'的总费用(包括总票价和服务总额)。 sql必须返回总票价为120 + 120 = 240,总服务为30 + 50 + 50 = 130。

谢谢! :)

6 个答案:

答案 0 :(得分:11)

首先,在您当前的表架构中,您无法区分已在不同票证中销售给同一乘客的服务。因此,您无法正确计算每张票的total_cost。您必须在ticket_id表中添加service

现在,如果您在ticket_id表中有service,则具有相关子查询的解决方案可能看起来像

SELECT t.*,
       (SELECT SUM(fare) 
          FROM passenger
         WHERE ticket_id = t.id) total_fare,
       (SELECT SUM(cost) 
          FROM service
         WHERE ticket_id = t.id) total_cost
  FROM ticket t

JOIN s

SELECT t.id, 
       p.fare total_fare,
       s.cost total_cost
FROM ticket t LEFT JOIN 
(
  SELECT ticket_id, SUM(fare) fare
    FROM passenger
   GROUP BY ticket_id
) p 
  ON t.id = p.ticket_id LEFT JOIN 
(
  SELECT ticket_id, SUM(cost) cost
    FROM service
   GROUP BY ticket_id
) s
  ON t.id = s.ticket_id

注意:两个查询都会考虑到乘客每张票可以拥有多项服务或根本没有服务这一事实。


现在使用您当前的架构

SELECT t.*,
       (SELECT SUM(fare) 
          FROM passenger
         WHERE ticket_id = t.id) total_fare,
       (SELECT SUM(cost) 
          FROM service s JOIN passenger p
            ON s.passenger_id = p.id
         WHERE p.ticket_id = t.id) total_cost
  FROM ticket t

SELECT t.id, 
       p.fare total_fare,
       s.cost total_cost
FROM ticket t LEFT JOIN 
(
  SELECT ticket_id, SUM(fare) fare
    FROM passenger
   GROUP BY ticket_id
) p 
  ON t.id = p.ticket_id LEFT JOIN 
(
  SELECT p.ticket_id, SUM(cost) cost
    FROM service s  JOIN passenger p
      ON s.passenger_id = p.id
   GROUP BY p.ticket_id
) s
  ON t.id = s.ticket_id

<小时/> 只需获得每张票的总票数

SELECT t.*,
       (SELECT SUM(fare) 
          FROM passenger
         WHERE ticket_id = t.id) +
       (SELECT SUM(cost) 
          FROM service s JOIN passenger p
            ON s.passenger_id = p.id
         WHERE p.ticket_id = t.id) grand_total
  FROM ticket t

SELECT t.id, 
       p.fare + s.cost grand_total
FROM ticket t LEFT JOIN 
(
  SELECT ticket_id, SUM(fare) fare
    FROM passenger
   GROUP BY ticket_id
) p 
  ON t.id = p.ticket_id LEFT JOIN 
(
  SELECT p.ticket_id, SUM(cost) cost
    FROM service s  JOIN passenger p
      ON s.passenger_id = p.id
   GROUP BY p.ticket_id
) s
  ON t.id = s.ticket_id

答案 1 :(得分:2)

您可以将三个表连接在一起,然后您可以直接执行SUM而不使用子选择。如果您需要每张票,您需要使用GROUP BY按ticket.id进行分组。

类似的东西:

SELECT t.id, SUM(p.fare) AS total_far, SUM(s.cost) AS total_cost
FROM 
    ticket t, passenger p, service s
WHERE t.id = p.ticket_id AND s.passenger_id = p.id 
GROUP BY t.id;

答案 2 :(得分:2)

SELECT 
    SUM(fare) as total_fare,
    SUM(cost) as total_service_cost
FROM
    ticket
left join passenger ON ticket.id = passenger.ticket_id
left join service ON passenger.id = service.passenger_id

答案 3 :(得分:0)

这个怎么样?

SELECT 
    SUM(fare) as total_fare,
    SUM(cost) as total_cost as total_service_cost
FROM
    ticket
JOIN passenger ON passenger.ticket_id = ticket.id
JOIN service ON passenger.id = service.passenger_id

如果您需要为每张票证求和,请添加GROUP BY ticket.id

答案 4 :(得分:0)

select
    t.code,
    sum(p.fare) as total_fare,
    sum(s.cost) as total_cost
from ticket as t
    inner join passenger as p on p.ticket_id = t.id
    inner join service as s on s.passenger_id = p.id
group by t.code

答案 5 :(得分:0)

这个怎么样?

with fares as(
select p.id id, p.ticket_id ticket_id, sum(coalesce(s.cost,0)) cost
  from passenger p left outer join service s
       on p.id = s.passenger_id
 group by p.id, p.ticket_id)
select q.ticket_id, sum(f.cost), sum(q.fare), sum(f.cost + q.fare)
  from fares f inner join passenger q
       on f.id = q.id
 group by q.ticket_id;