分组和汇总功能

时间:2013-12-10 02:09:59

标签: mysql sql database

我正在尝试使用union和group by聚合函数,但所有尝试都会导致缺少行或数据不正确。下面是两个产生我需要的数据的查询,现在我只需要将它们联合起来

以下是pastebin

上的SQL转储示例

SQL查询#1:

SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst
FROM orders as o, orders_product_line as opl, products as p
WHERE opl.order_id = o.id
AND p.id = opl.product_id
GROUP BY o.id

查询#1的结果

+----------+------------+------------+
| order_id | total_prod | total_inst |
+----------+------------+------------+
|        1 |       4200 |          0 |
|        2 |      40000 |          0 |
|        3 |    3600000 |          0 |
|        4 |      44500 |          0 |
|        5 |    1229800 |          0 |
|        6 |   45000000 |          0 |
+----------+------------+------------+

SQL查询#2:

SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst
FROM orders as o, orders_installation_line as oil, installations as i
WHERE oil.order_id = o.id
AND i.id = oil.intallation_id
GROUP BY order_id

查询#2的结果:

+----------+------------+------------+
| order_id | total_prod | total_inst |
+----------+------------+------------+
|        1 |          0 |       4675 |
|        2 |          0 |     255000 |
|        3 |          0 |      18880 |
|        4 |          0 |        600 |
|        5 |          0 |       3540 |
+----------+------------+------------+

这是我尝试在两个表中使用union

SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id GROUP BY o.id
UNION ALL
SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id GROUP BY order_id

结果

+----------+------------+------------+
| order_id | total_prod | total_inst |
+----------+------------+------------+
|        1 |       4200 |          0 |
|        2 |      40000 |          0 |
|        3 |    3600000 |          0 |
|        4 |      44500 |          0 |
|        5 |    1229800 |          0 |
|        6 |   45000000 |          0 |
|        1 |          0 |       4675 |
|        2 |          0 |     255000 |
|        3 |          0 |      18880 |
|        4 |          0 |        600 |
|        5 |          0 |       3540 |
+----------+------------+------------+

最后,这是我在阅读堆栈溢出的其他答案后尝试使用union:

SELECT *
FROM 
(
SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst
FROM orders as o, orders_product_line as opl, products as p
WHERE opl.order_id = o.id
AND p.id = opl.product_id
GROUP BY o.id

UNION ALL

SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst
FROM orders as o, orders_installation_line as oil, installations as i
WHERE oil.order_id = o.id
AND i.id = oil.intallation_id
GROUP BY order_id
) Q
GROUP BY Q.order_id

最后一次结合的结果:

+----------+------------+------------+
| order_id | total_prod | total_inst |
+----------+------------+------------+
|        1 |       4200 |          0 |
|        2 |      40000 |          0 |
|        3 |    3600000 |          0 |
|        4 |      44500 |          0 |
|        5 |    1229800 |          0 |
|        6 |   45000000 |          0 |
+----------+------------+------------+

我错过了什么?我需要最后一列total_inst来显示值。这是我要找的结果:

+----------+------------+------------+
| order_id | total_prod | total_inst |
+----------+------------+------------+
|        1 |       4200 |       4675 |
|        2 |      40000 |     255000 |
|        3 |    3600000 |      18880 |
|        4 |      44500 |        600 |
|        5 |    1229800 |       3540 |
|        6 |   45000000 |          0 |
+----------+------------+------------+

2 个答案:

答案 0 :(得分:0)

你的小组是对的......但我认为你不想要一个工会。试试这个:

select q1.order_id, q1.total_prod, q2.total_inst from 
(SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id GROUP BY o.id) q1, 
(SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id GROUP BY order_id) q2
where q1.order_id = q2.order_id

编辑:上面的查询只会检索由两个内部查询返回的order_ids。要包含order_id 6,您需要 LEFT JOIN 。但是,这不会得到q2结果中可能存在的记录,但不会得到q1的结果(相反的情况)。 FULL JOIN 会这样做,但我的理解是这些都没有在MySQL中实现。它们可以被模拟,如下所述:Full Outer Join in MySQL

select q1.order_id, q1.total_prod, q2.total_inst from 
(SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id GROUP BY o.id) q1
LEFT JOIN
(SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id GROUP BY order_id) q2
ON q1.order_id = q2.order_id
UNION
select q1.order_id, q1.total_prod, q2.total_inst from 
(SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id GROUP BY o.id) q1 
RIGHT JOIN 
(SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id GROUP BY order_id) q2
ON q1.order_id = q2.order_id

最终编辑:这是另一种方法的工作SQLFiddle。 http://sqlfiddle.com/#!2/deff12/12/0

答案 1 :(得分:0)

我同意马特的观点,你在这里需要的是加入/笛卡尔产品,而不是工会。尝试:

SELECT * FROM 
(SELECT o.id as order_id, SUM(price * quantity) as total_prod, FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id GROUP BY o.id) as q1 NATURAL JOIN
(SELECT o.id as order_id, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id GROUP BY order_id) as q2;
第一次编辑: 好的。所以基本上,如果id在orders_product_line而不是orders_installation_line,那么我们需要插入一个带有id的元组,total_prod的值和total_inst的值0。那是对的吗?所以尝试这样的事情:

(SELECT * FROM 
(SELECT o.id as order_id, SUM(price * quantity) as total_prod, FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id GROUP BY o.id) as q1 NATURAL JOIN
(SELECT o.id as order_id, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id GROUP BY order_id) as q2)
UNION 
(SELECT o.id as order_id, SUM(price * quantity) as total_prod, 0 as total_inst FROM orders as o, orders_product_line as opl, products as p WHERE opl.order_id = o.id AND p.id = opl.product_id AND opl.order_id NOT IN (SELECT id FROM orders_installation_line) GROUP BY o.id)
UNION
(SELECT o.id as order_id, 0 as total_prod, SUM(rate * hours) as total_inst FROM orders as o,  orders_installation_line as oil, installations as i WHERE oil.order_id = o.id AND i.id = oil.intallation_id AND oil.order_id NOT IN (SELECT id FROM orders_product_line) GROUP BY order_id);

这是如何工作的?它可能非常不理想,但希望它能得到结果。