MySQL查找特定列中最后一次出现的字符串模式

时间:2012-07-07 20:40:32

标签: mysql sql

我有一个mysql表,其中有一列例如叫名字。列数据具有特定模式nameBase + number。 E.g。

name
----------
test0
test1
test2
stack0
stack1
stack2

每次我想要向列中添加数据时,我必须找到特定nambeBase的最后一个数字,并添加新条目+数字+ 1.

例如,如果现在测试了,我必须将test3添加到db。

我的问题:1.检查nameBase是否已经存在于db(sth like contains)和2.find last nameBase数字的最佳方法是什么。例如。这里的测试是3.

更新:每个人,一次更新。我终于使用了java Pattern类。这么酷又容易。它使一切变得如此简单。我只是可以添加/ d到模式,然后我可以检查是否匹配名称,并可以使用模式组轻松访问第二部分。

5 个答案:

答案 0 :(得分:3)

此处的真正解决方案是更改数据库架构,将其拆分为两个列,即名称及其编号。然后通过

获取聚合MAX()变得微不足道
SELECT name, MAX(num) AS num FROM tbl GROUP BY name

但是,如果更改它不是一个选项,我建议使用REPLACE() 从列值中删除名称部分,在查询时仅留下数字部分,并获取聚合MAX()为此找到最高的现有数字:

SELECT
  MAX(REPLACE(name, <the name to search>, '')) AS maxnum
FROM tbl
WHERE 
  name LIKE '<the name to search>%'

或者代替LIKE,使用比LIKE更准确的正则表达式(如果名称包含其他名称,LIKE可能匹配)但更昂贵:< / p>

SELECT
  MAX(REPLACE(name, <the name to search>, '')) AS maxnum
FROM tbl
WHERE 
  name REGEXP '^<the name to search>[0-9]+$'

答案 1 :(得分:1)

我会使用带有两列的附加表来执行此操作,并在此表中存储每个名称和最后分配的ID。然后替换原始表中的nameBase+number列,其中name列是添加表的外键,number列是该条目的适当计数。

操作起来会更容易,也更有效率。

答案 2 :(得分:1)

如果可能的话,我会重组表格,将它们放在2个表(更好)或至少两个列(中)中。你所拥有的结构根本没有标准化: - /

不了解您的架构;这是我对双表解决方案的建议:(注意:这是标准化的,也遵循成语“不存储可以计算的”)

names
------
id  | name
01  | test
02  | stack

name_hits
-------
name_id | date
01      | 01/01/2001
01      | 01/15/2001
01      | 04/03/2001
02      | 01/01/2001
...

然后选择如下:

SELECT names.name, count(name_hits.id) as hits 
FROM names JOIN name_hits ON names.id=name_hits.name_id
GROUP BY names.id

并插入如下:

INSERT INTO name_hits SELECT id, NOW() FROM names WHERE name = "stack";

答案 3 :(得分:1)

假设您无法更改表格的结构,您可以按照自己的意愿行事。但是,它相当昂贵。

您想要做的是:

select name
from t
where left(name, length(<name parameter>)) = <name parameter>
order by name desc
limit 1

不幸的是,你的命名可能不允许这样做,因为你没有用零填充数字部分。

所以,以下解决了这个问题:

select name,
       cast(substring(name, length(<name parameter>), 1000) as int) as number
from t
where left(name, length(<name parameter>)) = <name parameter>
order by 2 desc
limit 1

这不是特别有效。此外,索引无法真正帮助解决这个问题,因为字符串的整理顺序与数字(test0,test1,test10,test100,test11等,而不是0,1,2,3,4 ......)不同。

如果可以的话,我会遵循建议多个列或表的其他人的建议。我只提供这种方法,您无需修改​​当前表。

答案 4 :(得分:1)

如果您无法更改架构,请尝试以下操作:

INSERT INTO names (name)
  SELECT CONCAT("stack", CAST(TRIM(LEADING "stack" FROM name) AS INT)+1) 
   WHERE name LIKE "stack%" ORDER BY name DESC LIMIT 1;

这个想法是:

  1. 选择“最高”的上一个值
  2. 这个名字的印章,
  3. 将剩余的字符串转换为int,
  4. 添加一个,
  5. 然后把名字重新放在上面。
  6. 我没有测试过这个...我希望它能引导你朝着正确的方向前进。

    请注意,我使用常量字符串“stack”作为示例,您可能希望使其动态化。