0

名前と呼ばれる列があるmysqlテーブルがあります。列データには、特定のパターンnameBase+numberがあります。例えば

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

列にデータを追加するたびに、特定のnambeBaseの最後の番号を見つけて、新しいエントリ+ number+1を追加する必要があります。

たとえば、今テストが来た場合、dbにtest3を追加する必要があります。

私の質問:1。nameBaseがdb(sth like contains)にすでに存在するかどうかを確認し、2。最後のnameBase番号を見つけるための最良の方法は何ですか。たとえば、ここでのテストは3です。

更新:皆さん、1回の更新。私はついにjavaPatternクラスを使用しました。とてもクールで簡単です。それはすべてをとても簡単にしました。/ dをパターンに追加するだけで、それが名前と一致するかどうかを確認し、パターングループを使用して2番目の部分に簡単にアクセスできます。

4

5 に答える 5

3

ここでの実際の解決策は、データベーススキーマを変更して、これを名前と番号の2つの列に分割することです。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は一致する可能性があります)よりも正確ですが、より高価です。

SELECT
  MAX(REPLACE(name, <the name to search>, '')) AS maxnum
FROM tbl
WHERE 
  name REGEXP '^<the name to search>[0-9]+$'
于 2012-07-07T20:45:35.373 に答える
1

これを2つの列を持つ追加のテーブルで行い、このテーブルに各名前と最後に割り当てられたIDを格納します。nameBase+number次に、元のテーブルのname列を、追加テーブルの外部キーであるnumber列と、そのエントリの適切な数である列に置き換えます。

これにより、操作がはるかに簡単で効率的になります。

于 2012-07-07T20:45:30.907 に答える
1

可能であれば、テーブルを再構築して、これらを2つのテーブル(より良い)または少なくとも2つの列(中)に配置します。あなたが持っている構造はまったく正規化されていません:-/

スキーマについてあまり知らなくても、これが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";
于 2012-07-07T20:47:39.220 に答える
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 ..。)。

可能であれば、複数の列またはテーブルを提案する他の人のアドバイスに従います。これは、現在のテーブルを変更する必要がない方法としてのみ提供しています。

于 2012-07-07T20:57:49.080 に答える
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. それに1つ追加します
  5. 次に、名前を元に戻します。

私はこれをテストしていません...それがあなたを正しい方向に導くことを願っています。

例として定数文字列「スタック」を使用したことに注意してください。おそらくそれを動的にしたいと思うでしょう。

于 2012-07-07T21:01:38.370 に答える