簡體   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