2012-07-07 69 views
0

我有一個mysql表,其中有一列,例如,所謂的名字。列數據具有特定的模式名稱BASE +編號。例如。MySQL找到特定列中最後一次出現的字符串模式

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

每次我想將數據添加到列,我必須找到具體nambeBase的最後一個號碼,並添加新條目+數字+ 1。

例如,如果現在測試來了,我必須添加test3到db。

我的問題:什麼是最好的方法來檢查,如果nameBase已經存在於數據庫中(例如包含)和2.找到最後一個名稱的數字。例如。這裏的測試是3.

更新:每個人,一個更新。我終於使用了java Pattern類。太酷了,很容易。它使一切變得如此簡單。我可以將/ d添加到模式,然後我可以檢查它是否與名稱匹配,並可以使用模式組輕鬆訪問第二部分。

+2

這是否適用於性能至關重要的交易系統?如果是這樣,你可能應該改變結構以在單獨的列中包含名稱和編號,並在其上包含複合索引。 – 2012-07-07 20:44:17

+0

MySQL + MyISAM有一個有趣的功能:請參閱http://dev.mysql.com/doc/refman/5.6/en/example-auto-increment.html/MyISAM Notes。 – biziclop 2012-07-07 20:47:15

+0

謝謝,但我無法更改架構。我必須按照他們的要求。 – Sara 2012-07-07 20:54:20

回答

3

這裏真正的解決方法是改變數據庫模式,將其拆分成兩個列,名稱和編號。它變得微不足道然後通過

SELECT name, MAX(num) AS num FROM tbl GROUP BY name 

拿到總MAX()但是,如果改變它是不是一種選擇,我會建議使用REPLACE()刪除從列值只留下數部分的名部分查詢時,並獲得了總MAX()找到現有的最高數量爲它:

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

或代替LIKE,使用正則表達式,這比更準確(萬一名稱中包含另一個名稱,LIKE可能匹配),但更昂貴:

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

我會做一個附加的兩列的表,並在這個表中存儲每個名稱和最後分配的ID。然後將原始表中的nameBase+number列替換爲name列,該列是加法表的外鍵,並且number列是該條目的適當計數。

這將更容易和更有效地操縱。

+0

謝謝,但我無法更改架構。這是客戶要求我的要求。我必須按照他們想要的去做! – Sara 2012-07-07 20:55:30

+0

@Sara。哎喲。下面的邁克爾對你有一個合理的答案。但它不會很漂亮,因爲您無法按照您需要的方式對列進行索引以進行有效更新。 – 2012-07-07 20:57:17

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"; 
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 ......)不同。

如果可以的話,我會按照建議多列或多表的其他人的建議。我只提供這種方法,您不必修改當前表格。

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. 將其餘的字符串作爲整型,
  4. 加1就可以了,
  5. 然後把名字放回去。

我還沒有測試過這個......我希望它能引導您朝着正確的方向前進。

請注意,我已經使用了一個常量字符串「堆棧」作爲示例,您可能會想要使這種動態。

相關問題