什么是替代联接查询

时间:2019-02-24 10:13:04

标签: mysql

表格:items

+---+-----------+
|id |    name   |
+---+-----------+
| 1 | Product-A |
| 2 | Product-B |
+---+-----------+

表格:orders

+---+-----+------------+
|id |price| orderer_id |
+---+-----+------------+
| 1 | 100 |      53    |
| 2 | 240 |      54    |
| 3 | 200 |      54    |
| 4 | 150 |      53    |
+---+-----+------------+

表格:item_order

+----+--------+---------+----------+
| id |order_id| item_id | quantity |
+----+--------+---------+----------+
| 1  |   1    |    1    |     2    |
| 2  |   1    |    2    |     3    |
| 3  |   2    |    2    |     2    |
| 4  |   3    |    1    |     1    |
| 5  |   3    |    2    |     1    |
| 6  |   4    |    1    |     2    |
| 7  |   4    |    2    |     2    |
+----+--------+---------+----------+

要提取的内容:

对于每个orderer_idnumber_of_ordertotal_quantitytotal_price

+---------+-----------------+----------------+-------------+
| orderer | number_of_order | total_quantity | total_price |
+---------+-----------------+----------------+-------------+
|   53    |        2        |        9       |     250     |
|   54    |        2        |        4       |     440     |
+---------+-----------------+----------------+-------------+

当前方法:     使用相关子查询

select orderer_id as orderer, 
    count(*) as number_of_order, 
    sum(select quantity from item_order where item_order.order_id = orders.id) as total_quantity, 
    sum(price) as total_price
from orders
order by orderer_id

是否可以通过将item_orderorders结合来解决?如果是,怎么办?

我认为的另一种方法-

  1. select ... from orders
  2. select ... from item_order
  3. 根据application layer的要求组合和格式化

可以假设,ordersitem_order表将变得更大,哪种解决方案会更好?

2 个答案:

答案 0 :(得分:1)

由于从ordersitem_order的一对多关系,在子查询中执行聚合,而在导出的表中JOIN进行聚合更容易:

SELECT o.orderer_id,
       COUNT(o.id) AS number_of_order,
       SUM(io.quantity) AS total_quantity,
       SUM(o.price) AS total_price
FROM orders o
JOIN (SELECT order_id, SUM(quantity) AS quantity
      FROM item_order
      GROUP BY order_id) io ON io.order_id = o.id
GROUP BY o.orderer_id

输出:

orderer_id  number_of_order total_quantity  total_price
53          2               9               250
54          2               4               440

Demo on dbfiddle

我希望它比相关子查询更快,因为必须对orders表中的每一行执行该查询,而对派生表的查询虽然更复杂,但只执行一次。我还希望它比在应用程序层中执行两个查询和合并的选项更快。

答案 1 :(得分:0)

请检查此

模式(MySQL v8.0)

CREATE TABLE orders (
  `id` INTEGER,
  `price` INTEGER,
  `orderer_id` INTEGER
);

INSERT INTO orders
  (`id`, `price`, `orderer_id`)
VALUES
  ('1', '100', '53'),
  ('2', '240', '54'),
  ('3', '200', '54'),
  ('4', '150', '53');

CREATE TABLE item_order (
  `id` INTEGER,
  `order_id` INTEGER,
  `item_id` INTEGER,
  `quantity` INTEGER
);

INSERT INTO item_order
  (`id`, `order_id`, `item_id`, `quantity`)
VALUES
  ('1', '1', '1', '2'),
  ('2', '1', '2', '3'),
  ('3', '2', '2', '2'),
  ('4', '3', '1', '1'),
  ('5', '3', '2', '1'),
  ('6', '4', '1', '2'),
  ('7', '4', '2', '2');

查询#1

with cte0 as 
(
select 
  orderer_id orderer,
  count(distinct o.id) number_of_order,
  sum(io.quantity) total_quantity
from orders o
inner join item_order io
  on io.order_id = o.id
group by orderer_id
), cte1 as 
( 
select 
  orderer_id, 
  sum(price) total_price
from orders
group by orderer_id
)
select orderer, number_of_order, total_quantity, total_price from cte0
inner join cte1 
  on cte0.orderer = cte1.orderer_id;

| orderer | number_of_order | total_quantity | total_price |
| ------- | --------------- | -------------- | ----------- |
| 53      | 2               | 9              | 250         |
| 54      | 2               | 4              | 440         |

View on DB Fiddle