我有4个表,客户,产品,销售和销售商品。我使用下面的查询从中提取数据。
SELECT (
SELECT c.name
FROM Customers c
WHERE s.customer_id=c.id
) customer
,(
Select group_concat(description)
FROM (
SELECT si.id
,si.sale_id
,concat("x", si.Qty, " ", p.name, " ",(si.total)) description
FROM Sale_Items si
LEFT JOIN Products p ON p.id = si.product_id
) p
where s.id = Sale_ID
GROUP BY Sale_ID
) detail,
s.total
FROM Sales s
查询会产生结果,但结果变慢,仅记录2000条(需要114秒才能完成)
Customer Product Total
--------------------------------------
James x1 ItemA 10.00 75.00
x3 ItemB 15.00
x1 ItemC 20.00
Mark x2 ItemA 10.00 50.00
x2 ItemB 15.00
Bisi x1 ItemC 20.00 30.00
x2 ItemA 10.00
我怎样才能更快?
在这里尝试过
答案 0 :(得分:1)
如果我们要坚持使用相关子查询,则可以消除内联视图p
。
将从Sales
中检索到的每一行都变为现实。外部查询的WHERE
子句中的谓词不会“推”入视图。因此,物化视图(或MySQL术语中的“派生表”)将是一个完整的集合,然后,我们将从中挑选出几行。我们将对Sales
中的每一行重复一次。
展开该派生表应该为我们带来一些性能优势。对于从Sales
返回的少量行并定义了合适的索引,这将是一种合理的方法。也就是说,如果我们使用WHERE
子句限制外部查询检查的行数。由于有大量的行,那些相关的子查询将降低性能。
SELECT ( SELECT c.name
FROM Customers c
WHERE c.id = s.customer_id
) AS customer
, ( SELECT GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n')
FROM Sale_Items si
LEFT
JOIN Products p
ON p.id = si.product_id
WHERE si.sale_id = s.id
) AS detail
, s.total
FROM Sales s
WHERE ...
ORDER
BY ...
如果查询返回的是Sales
的所有行,而我们正在进行整个Bloomin'设置,那么我倾向于避免相关的子查询。 (这是因为子查询是针对外部查询返回的每一行执行的。就性能而言,这些子查询将吃掉我们的午餐,并且返回了大量行。)
假设id
在customers
中是唯一的,那么使用连接操作通常会更好。
SELECT c.name AS customer
, d.detail
, s.total
FROM Sales s
LEFT
JOIN Customers c
ON c.id = s.customer_id
LEFT
JOIN ( SELECT si.sale_id
, GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n') AS detail
FROM Sale_Items si
LEFT
JOIN Products p
ON p.id = si.product_id
GROUP
BY si.sale_id
) d
ON d.sale_id = s.id
ORDER
BY ...
内联视图d
对于大型集合将变得昂贵;但至少我们只进行一次查询,将结果具体化为“派生表”。然后,外部查询可以运行,并从派生表中检索行。