2017-10-11 15 views
0

です。まず、MySQLのクエリでこれを完全に実行したいと考えています。MySQLインボイス番号の範囲は、

私はこの

from_invoice_no to_invoice_no total_invoices 
INV001    INV005   5 
001    010    7 
INVOICE333   INVOICE339  6 
001INV    009INV   4 

パターンが固定できない請求書番号のような出力に何かしたい請求書番号のシリーズ

invoice_number 
INV001 
INV002 
INV003 
INV004 
INV005 
001 
002 
003 
006 
007 
009 
010 
INVOICE333 
INVOICE334 
INVOICE335 
INVOICE337 
INVOICE338 
INVOICE339 
001INV 
002INV 
005INV 
009INV 

を持っています。将来変更される可能性があります。

これを達成するために手伝ってください。

ありがとうございます。

+0

請求書番号には常に2つの部分があります.1つの部分は連続した数字で、残りの部分は連続した非数字です。また、請求書番号は「001INV003FOO1234BAR」のようになりますか? – Binarus

+0

はい、「PRCMMU1718/00057」、「PRCMMU1718/00058」、「AQW1025」、「AQW1028」、「AQW1030」、「1258POC」、「1259POC」... – pmenezes

+0

はい、許可されていますか(つまり、 )を使用してそのテーブルに2つの列を追加するか、新しいテーブルを作成しますか? – Binarus

答えて

0

この問題を解決する方法と、醜いが簡単に理解できるコードを提供する方法を、一般的な考え方を最初に示します。次に、問題の内容と解決方法について説明します。

STEP 1:最初のステップのためのグループ化基準

の導出、私はあなたがあなたのテーブルに追加の列を作成する権利(権限)を持っていると仮定します。それをinvoice_textと名付けましょう。今、一般的な考え方は、 "テキストパターン"だけが残るように請求書番号からすべての数字を削除することです。次に、テキストパターンでグループ化することができます。

あなたが次のことを行うことができ、あなたはすでに上記の列を作成したと仮定すると:あなたはinvoice_textの桁なしで純粋なテキストパターンを持つことになりますし、グループ化のためにそれを使用することができることを行わした後

UPDATE Invoices SET invoice_text = REPLACE(invoice_number, '0', ''); 
UPDATE Invoices SET invoice_text = REPLACE(invoice_text, '1', ''); 
UPDATE Invoices SET invoice_text = REPLACE(invoice_text, '2', ''); 
... 
UPDATE Invoices SET invoice_text = REPLACE(invoice_text, '9', ''); 

SELECT COUNT(invoice_number) AS total_invoices FROM Invoices 
    GROUP BY invoice_text 

これは素晴らしいですが、まだあなたが望むものではありません。各グループの最初と最後の請求書番号は表示されません。

STEP 2:あなたのテーブル内の1つの以上の列を作成し、このステップでは、各グループ

ための最初と最後の請求書を導出します。それをinvoice_digitsと名付けましょう。名前が意味するように、それは "パターンテキスト"なしで純粋な請求書番号だけを取ることを意味します。

あなたはその列を持っていると仮定すると、次の行うことができます:

SELECT 
    MIN(invoice_digits) AS from_invoice_no, 
    MAX(invoice_digits) AS to_invoice_no, 
    COUNT(invoice_number) AS total_invoices 
FROM Invoices 
GROUP BY invoice_text 
:今

UPDATE Invoices SET invoice_digits = REPLACE(invoice_number, 'A', ''); 
UPDATE Invoices SET invoice_digits = REPLACE(invoice_digits, 'B', ''); 
UPDATE Invoices SET invoice_digits = REPLACE(invoice_digits, 'C', ''); 
... 
UPDATE Invoices SET invoice_digits = REPLACE(invoice_digits, 'Z', ''); 

を、あなたは(「パターンテキスト」なし)最小と最大の請求書番号を取得するには、その列を使用することができます

の問題とあなたによると、彼らに

1)を解決する方法あなたは最小と最大のフルインボイス番号のテキストを取得したいと考えています。上記の解決策では、テキスト部分のない最小および最大請求書番号テキストのみが表示されます。つまり、数字のみです。

JOINをこれを修正することができますが、私はあなたがこれを主張しないと想像することができます:-)、そして一般的なアイデアをより明確にしないので、私はこれを残していますあなたへ。興味があれば、私たちに知らせてください。

2)実際の請求書)である、すなわち何(何桁を決定することは困難かもしれません。たとえば、INV001INV002のような請求書番号がある場合、これは問題ありませんが、INV001/001,INV001/002,INV002/003などがある場合はどうなりますか?この例では、私のコードは001001001002002003を実際の請求書番号とし、それを使って最小値と最大値が何であるかを決定します。

この場合、これはあなたがしたいことではないかもしれません。これを回避する唯一の方法は、数字を考慮する必要があるものとそうでないものを徹底的に考え、それに応じてコードを適合させることです。

3)現在のところ、私のコードでは文字列の比較を使用して、最小および最大の請求書番号を取得しています。これは数値を数値として比較する以外の結果をもたらす可能性があります。それが何を意味するのか疑問に思っている場合:'19''9'を文字列として比較し、199と数字を比較してください。

これが問題の場合は、を使用してテキストを数値に変換してから、MAXまたはMINに入力してください。しかし、これには独自の注意点がありますのでご注意ください。

数値が非常に長いインボイス番号がMySQLの数値データ型に適合しない場合、この方法は失敗します。 /のような文字を(2で説明した問題のため)数字にすると、MySQLは数字に変換できないため、これも失敗します。

数値に変換する代わりに、の値を先行するゼロで埋め込むこともできます。たとえば、MySQLのLPAD関数を使用します。これは上記の問題を回避し、/のような非数字が含まれていても数値を期待どおりにソートしますが、数字の文字列の最大長を事前に知る必要があります。

4)コードは醜いです!数字の文字列を取得するためにUPDATE文を実行して、AからZまでのすべての文字を1つずつ削除する必要がありますか?

実際、さらに悪化しています。私はちょうどと仮定しましたが、あなたの請求書には「テキスト文字」AZしかありません。しかし、Unicodeには、ロシア語や中国語の文字、特殊文字、つまり何千もの異なる文字が定義されている可能性があります。

残念ながら、AFAIK、MySQLはまだREGEX-REPLACE機能を提供していません。適切なUDF(ユーザー定義関数)でMySQLを拡張しない限り、この問題を解決する機会はありません。問題を認識してMySQLにそのような機能を追加したクールな人がいます。ライブラリを推薦するので、SOには、単に "Googleの正規表現の置き換え"のGoogleに落胆しているようだ。

このようにMySQLを拡張すると、UPDATEの醜い束を置き換えることができます。これは、桁数字/テキストを1つずつ削除します(REGEXを使用して、すべての桁またはすべての非桁すぐに)。

UPDATE ... SET ... = REPLACE(REPLACE(REPLACE(...)))を実行して1つのステートメントですべての更新を適用することで、多くのUPDATEステートメントを避けることができます。しかし、これはさらに醜いとエラーが発生しやすいので、あなたが問題について深刻な場合、あなたは本当にREGEX - REPLACEによってMySQLを拡張する必要があります。

5)解決策は、テーブルに新しい列を作成する権限がある場合にのみ機能します。

これはそのままのソリューションに当てはまります。しかし、私はそれが一般的なアイデアをはっきりと理解できるようにするために、その道を行くことを選択しました。元のテーブルに列を追加する代わりに、純粋なテキスト/数字を格納する新しいテーブルを作成することもできます(このテーブルは一時的なものかもしれません)。

さらに、MySQLでは計算値によるグループ化がサポートされているため、追加の列/テーブルはまったく必要ありません。最善の方法は何かを自分で決めるべきです。

+0

あなたがポイント2で言及したように、それはまさに私のケースです。接頭辞と接尾辞には、英数字とそれに続く増分の数字を使用できます。請求書パターンはシステムで定義されていません。私はこれを行う他の方法を見つける必要がありますPHPを介して可能性があります – pmenezes

+0

パターンに属して何が実際の番号に属しているルールが存在しない限り、ソフトウェアでこれを解決するチャンスはありません。私があなたのコメントを得たならば、数字もパターンの一部になる可能性があります。たとえば、INV001とINV002がある場合、パターンがINV00で、実際の数が1と2であるかどうか、またはパターンがINV0であるかどうかを知ることさえできません実際の数字は「01」と「02」であり、パターンが「INV」であり、実際の数字が「001」と「002」である。 – Binarus

関連する問題