2012-07-07 2 views
0

예를 들어 열이있는 mysql 테이블이 있습니다. 불리는 이름. 열 데이터에는 특정 패턴 nameBase + number가 있습니다. 예 :MySQL은 특정 열에서 문자열 패턴의 마지막 항목을 찾습니다.

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

나는 컬럼에 데이터를 추가 할 때마다, 나는 특정 nambeBase의 마지막 번호를 찾아 새 항목 + 수 + 1을 추가해야합니다. 이제 테스트가 온 경우

예를 들어, 나는 dB로 TEST3을 추가해야합니다.

내 질문 : nameBase 이미 DB에 존재 (STH 등 포함) 마지막 nameBase 번호를 2.find 경우 1. 확인하는 가장 좋은 방법은 무엇입니까. 예 : 모두, 하나의 업데이트 : 여기 시험 3.

업데이트입니다. 나는 자바 패턴 클래스를 마침내 사용했다. 너무 시원하고 쉽게. 모든 것이 그렇게 단순 해졌습니다. 방금/d를 패턴에 추가 한 다음 이름과 일치하는지 확인하고 패턴 그룹을 사용하여 두 번째 부분에 쉽게 액세스 할 수있었습니다.

+2

이 성능이 중요한 트랜잭션 시스템에 대한인가? 그렇다면 구조체를 변경하여 별도의 열에 이름과 번호가 있고 복합 인덱스가 있어야합니다. 참조 http://dev.mysql.com/doc/refman/5.6/en/example-auto-increment.html /의 MyISAM 주 : –

+0

의 MySQL +의 MyISAM 흥미로운 기능이 있습니다. – biziclop

+0

감사합니다.하지만 스키마를 변경할 수 없습니다. 나는 그들의 요구 사항을 그대로 따라야 만한다. – Sara

답변

3

여기 실제 솔루션은 데이터베이스 스키마를 두 개의 열로 나눠서 변경하는 것입니다. 이름과 번호입니다. 그것을 변경하는 옵션이없는 경우, 그러나

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

를 통해 집계 MAX()를 얻을 후 사소한되고, 나는 쿼리 할 때 REPLACE()에이 수만 부분을 떠나는 열 값의 이름 부분을 제거하여 추천 할 것입니다 , 그리고 가장 높은 기존 번호를 찾기 위해 그 집계 MAX()를 얻을 : LIKE의 대신

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

또는를, 정규 표현식을 사용하여,,881보다 더 정확하다(이름이 다른 이름을 포함하는 경우, LIKE 일치 수)하지만 더 비싼 :

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

나는 추가로 두 개의 열이있는 테이블과 저장이 테이블의 각 이름과 마지막으로 할당 된 ID로이 작업을 수행 할 것입니다. 그리고 다음 name 열, 추가 테이블에 외래 키 및 number 열에있는 해당 항목에 대한 적절한 수있는 당신의 원래 테이블에 nameBase+number 열을 교체합니다.

훨씬 쉽게 조작하는 것이 더 효율적입니다.

+0

감사하지만 스키마를 변경할 수 없습니다. 이것은 고객이 저에게 요구 한 요구 사항입니다. 그들이 원하는대로 따라야 해! – Sara

+0

@Sara. 아야. 그럼 아래의 마이클은 당신에게 합당한 대답을합니다.하지만 효율적인 업데이트를 위해 필요한 방식으로 열을 인덱싱 할 수 없기 때문에 매우 예쁘지는 않을 것입니다. –

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. 이 하나를 추가, int로 나머지 문자열을 캐스팅
  5. 다음에 이름을 다시 입력하십시오. 나는이 테스트를하지 않은

은 ... 나는 그것이 올바른 방향으로 리드를 바랍니다. 내가 예를 들어 상수 문자열 "스택"을 사용했다

주, 당신은 가능성이 동적을 확인하는 것이 좋습니다.

관련 문제