繁体   English   中英

如何改进联合查询?

[英]How to improve union query?

我有一个“工作”的查询,但速度很慢,感觉很差,我不想每次添加/删除供应商时都更新!

基本上我有一个“价格”表,对于每个供应商,我需要根据他们最长的代码匹配来获得他们的代码价格(这是有效的),我对每个供应商 ID 重复这个,然后将它们结合在一起,最后加入供应商名称对结果

商品代码 ABC123456

select t1.*, s.name from
(
(Select * from prices where ABC123456 like CONCAT(code_prefix , '%') AND supplier_id = 1
ORDER BY LENGTH(code_prefix) Desc Limit 1)

UNION

(Select * from prices where ABC123456 like CONCAT(code_prefix , '%') AND supplier_id = 2
ORDER BY LENGTH(code_prefix) Desc Limit 1)

UNION

(Select * from prices where ABC123456 like CONCAT(code_prefix , '%') AND supplier_id = 3
ORDER BY LENGTH(code_prefix) Desc Limit 1)

... for each supplier

) t1

join supplier s on t1.supplier_id = s.id
order by buy_price asc 

1)如何为任意数量的供应商自动运行此程序(即为供应商表中的每个供应商运行,然后加入每个供应商的最佳结果) - 我无法理解它

2)性能不是很好,每个查询 300 毫秒,我也有 400000 个代码(在代码表中)运行。 我应该作为 StoredProc 执行此操作吗? 虽然它应该只在我们每个供应商每月更新 1 或 2 次定价更新时才运行,但这会产生很大的不同吗?

3)是否可以填充一个新表 price_order(代码,序列),其中代码来自上面,然后序列是供应商 ID 的价格顺序(从低到高),我可以这样做,这是一个应用程序,但有没有更聪明的在 DB 中如何获得更好的性能?

目前正在运行 10.0.27-MariaDB,但如果真的需要,可能会更改!

提前致谢

更新要求

价格表(其他列也存在!)

+---------------+--------------+-----------+
| code_prefix   | suppler_id   | price.    |
+---------------+--------------+-----------+
| ABC123        | 1            | 100       |
| ABC1          | 1            | 123       |
| ABC177        | 1            | 723       |
| ABC12         | 2            | 111       |
| ABC           | 2            | 222       |
| ABC111        | 3            | 001       |
| AB            | 3            | 234       |
| A             | 4            | 010       |
| B             | 4            | 710       |
+---------------+--------------+-----------+

我们有另一个代码表,我们需要在价格表中查找前缀

+---------------+
| code          |
+---------------+
| ABC123456     |
| ABC155555     |
| ABC12         |
| ABC7777777    |
+---------------+

因此,对于代码表中的每一行,我需要每个供应商的最佳/最长匹配

so code ABC123456 will return
+---------------+--------------+-----------+
| code_prefix   | suppler_id   | price     |
+---------------+--------------+-----------+
| ABC123        | 1            | 100       |
| ABC12         | 2            | 111       |
| AB            | 3            | 234       |
| A             | 4            | 010       |
+---------------+--------------+-----------+


code ABC155555 will return
+---------------+--------------+-----------+
| code_prefix   | suppler_id   | price     |
+---------------+--------------+-----------+
| ABC1          | 1            | 123       |
| ABC           | 2            | 222       |
| AB            | 3            | 234       |
| A             | 4            | 010       |
+---------------+--------------+-----------+

然后我们需要按价格升序对结果进行排序,并连接供应商 ID 以提供供应商订单

+------------+----------------+
| code       | suppler_order  |
+------------+----------------+
| ABC123456  | 4,1,2,3        |
| ABC155555  | 4,1,2,3        |
| ...        | ...            |
+------------+----------------+

我希望它更清楚,谢谢 r

首先定义一个视图以获取与每个供应商的每个代码前缀匹配的所有行(如果您有更新的 MariaDB 版本,您可以使用 CTE)。

CREATE VIEW supplier_codes AS
SELECT DISTINCT c.code, p.code_prefix AS code_prefix, p.supplier_id, p.price
FROM codes AS c
JOIN prices AS p ON c.code LIKE CONCAT(p.code_prefix, '%');

然后,您可以使用常见的习惯用法来获取每个供应商 ID 的代码前缀最大长度的行。

SELECT t1.*
  FROM supplier_codes AS t1
  JOIN (
    SELECT supplier_id, MAX(LENGTH(code_prefix)) AS maxlength
    FROM supplier_codes
    GROUP BY supplier_id
  ) AS t2 ON t1.supplier_id = t2.supplier_id AND LENGTH(t1.code_prefix) = t2.maxlength

然后,您可以将其与codes表连接起来,以获得每个代码的分组结果。

SELECT c.code, GROUP_CONCAT(DISTINCT sc.supplier_id ORDER BY sc.price) AS supplier_order
FROM codes AS c
JOIN (
  SELECT t1.*
  FROM supplier_codes AS t1
  JOIN (
    SELECT supplier_id, MAX(LENGTH(code_prefix)) AS maxlength
    FROM supplier_codes
    GROUP BY supplier_id, code
  ) AS t2 ON t1.supplier_id = t2.supplier_id AND LENGTH(t1.code_prefix) = t2.maxlength
) AS sc ON c.code = sc.code
GROUP BY c.code;

演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM