MySQL 符合部分或相似描述的项目

MySQL MATCH ITEMS by partial or similar DESCRIPTION

大家好,我想弄清楚如何匹配具有相似但并非总是相同名称或名称关键差异的某些产品。

事情是这样的。

我选择了一个特定类别的产品,它是一些汽车零件不能进入的:)。

所以购买的人有时会添加描述 'this and that L' 或 'this and that R' 这意味着该部分是左或右,它们单独出售,或者您可以成对购买,但为了这样做,我需要将所有确切的左与右匹配。更复杂的是,每个在采购工作的人都有自己独特的写作风格,有时L会在中间有时在最后,有时斜杠/L很多,还有product_id 在大多数情况下应该一个接一个地说 10001 L 和 10002,R 但不是一般情况下,我的最终 sintax 也应该有一个条件,我想看看我的匹配 L 的股票是否不同于匹配 R 的股票,即成对购买的选项总是可用的。

这里是 table

的例子

所以我想按品牌分组,以某种方式按描述进行匹配,并在库存来自匹配 L <> 库存来自匹配 R 的条件下显示结果。

欢迎任何如何攻击描述字符串的想法。我应该指出,仅从字符串中分离出 L 或 R 并不明智,因为一个品牌可以有许多匹配对。另外我应该为所有匹配组中的所有项目分配像 L 或 R 这样我可以计算它们的差异我猜

脏数据万岁。您最好的做法 long-term 是在您的 table 中添加一个名为“手”的列,并让您​​的采购代理正确填充它。但你知道的。

同时,我建议您向数据库中添加一个 VIEW,这样您就可以查看 table,就好像它有“手”列一样。在您看来,额外列的定义将包含一个又大又丑的 CASE WHEH THEN 语句来计算“hand”的值。

为什么要这样做?您从产品描述中提取惯用手的业务规则没有明确定义,您将不得不弄乱这个 VIEW 以让它为您的所有各种情况做正确的事情。如果您将其定义为 VIEW,您将能够轻松地检查结果以确保它们是正确的。

你会想做这样的事情:

CREATE OR REPLACE VIEW inventory_with_hand AS
SELECT *,
       CASE 
       WHEN description LIKE '%/LEFT%' THEN 'L'    /* /LEFT */
       WHEN description LIKE '%/RIGHT%' THEN 'R'   /* /RIGHT */
       WHEN description LIKE '%/L %' THEN 'L'      /* /L space */
       WHEN description LIKE '%/R %' THEN 'L'      /* /R space */
       WHEN RTRIM(description) LIKE '%L' THEN 'L'  /* L at end of string */
       WHEN RTRIM(description) LIKE '%R' THEN 'R'  /* R at end of string */
       WHEN description LIKE '% L %' THEN 'L'      /* space L space */
       WHEN description LIKE '% R %' THEN 'R'      /* space R space */
       ELSE '' END hand
  FROM inventory;

获得此视图后,您可以使用它来观察您的数据,看看您是否正确处理了 L/R 问题。使用这样的查询并滚动浏览结果。 (https://www.db-fiddle.com/f/haKdYj2G8eb9rdMZCPvQk2/1)

  SELECT description, hand
    FROM inventory_with_hand
   ORDER BY hand<>'', description, hand;

希望您会看到大量正确处理的数据和一些错误处理的数据。您可以向视图中的 WHEN THEN 级联添加新案例,直到正确处理数据。

WHEN THEN 适用于此应用程序,因为它与 if / else if / else if / else 具有相同的结构。 SQL 按照您指定的顺序处理 WHEN THEN 子句。当一个匹配时,匹配过程停止。

获得正确的 L/R 值后,您可以继续搜索匹配对的查询。有很多方法可以处理配对与脏数据的匹配。一个可能适合你的是:

查找 description 个彼此仅相差几个字符的字符串。 Levenshtein distance between the strings is good for this. There's a MySQL stored function 由 Kevin Woblick 在 Github 上计算得到。

这是一个按品牌、ID 的接近程度、L 和 R 变体的存在以及 Levenshtein 距离搜索配对的查询。

SELECT l.description, 
       LEAST(r.stock, l.stock) pairstock, 
       l.stock lstock, 
       r.stock rstock
   FROM inventory_with_hand l
   JOIN inventory_with_hand r
           ON l.id <> r.id            /* L and R must have different ids */
          AND l.hand = 'L'            /* left */
          AND r.hand = 'R'            /* right */
          AND ABS (l.id - r.id) < 10  /* id values close enough */
          AND l.brand = r.brand      /* same brand */
          AND LEVENSHTEIN(l.description, r.description) <= 5

不幸的是,这不会完美地工作。但值得一试。

我使用 5 作为 Levenshtein 距离限制来解释 /LEFT/RIGHT 之间的差异。如果你只有 /L/R,你可以使用 1,你的查询会变得更可靠。

注意:LEVENSHTEIN 存储的函数非常慢。尝试通过首先匹配其他事物来缩小其用途。我通过 id 和 brand 缩小了范围。

再次感谢琼斯的输入,而你正忙着帮助我 我正在尝试一些匹配 string_length 的选项,条件是 ID 仅高或低两个数字,并且匹配对 L.stock 和 R.stock 之间的差异不为零,并且股票必须更高比零

我必须说取得了一些不错的成绩

SELECT id, description, LENGTH(description), brand, stock FROM data a 
               WHERE EXISTS (
               SELECT 1 FROM data b
               WHERE length(a.description) = length(b.description)
               AND a.id <> b.id
               AND b.id- a.id BETWEEN -2 AND 2
               AND a.stock - b.stock <> 0
               AND a.stock > 0
               AND b.stock > 0)

按长度排序(描述)描述

LEVENSTHEIN 函数看起来真的很有趣,我正在尝试找出创建该函数的所有变量,以便我可以对其进行优化而不是复制粘贴...

乍一看,我能看到的是字符串的最大长度设置为 255,这将是应用时选择的最大数字,然后他声明了一些字符串或子字符串及其长度,然后就是一大堆 J-s、i-s、c-s,不管他妈的是什么……看起来很重要 :) 无论如何……

我将 ABS 设置得较低,因为它们中的大多数只是 +-1,有时是,但即使很难,将距离设置为 1 或 5 似乎也是合乎逻辑的,例如。 R 或 RIGHT 它只是不会做。我必须将它设置为至少 20 才能获得满足必要条件的完整对列表。

我用它来测试生产能力,它用 20 秒的时间导出包含完整项目列表的 CSV 文件,然后导入到 ERP 中,作为补货的候选对象。

后来我开始对那些不符合所有条件的项目进行预制检查,并再次得到一些异常值。

这里我们有4id; 2Ls & 2Rs but 3 pairs cause conditions were meeted: L.id <> R.id ,它们在范围内,同一品牌 ...

我注意到 descrp 字符串包含一个数字子字符串,它基本上类似于制造商代码或类似的东西,我已经创建了一个 DIGITS FUNCTION return 字符串中的所有数字。

L 的代码总是低于 R 的代码

在这种情况下我们有 (较低的ID有较高的代码,通常是它的比例)

我的数字函数将return字符串中的所有数字

所以从这个'KRAJNIK VW VO-ES-8215 L T-4 90->'

我会得到 8215490 它的匹配对应该是 8217490

我在想通过那些子串中的位置隔离唯一的字符,这些子串中的位置是 L 的数字 5 和 R 的数字 7 并将这种关系命名为条件唯一不同的字符并且它在相同位置上的 L 应该小于R,但在错配示例中也是如此。

也许我应该嘿,如果一个 L id 与 R.ids 匹配,请选择更近的一个 但 33214 与 33213 和 33215 相匹配,两者具有相同的距离,并且更高或更低的规则不适用于整个集合,有时 L.id > R.id...

总有一件事情是肯定的,L.code < R.code 编辑:这不再是确定的了……我已经从库存中提取了旧数据; 到处都是德州

这是一件棘手的事情, 总共只有 8 个项目是异常值,在这一点上甚至没有意义,我相信公司明智,但是当你想做对的时候,呵呵....