47

SQL を使用してフルネーム フィールドからファースト ネーム、ミドル ネーム、ラスト ネームを解析するにはどうすればよいですか?

フルネームと直接一致しない名前を一致させる必要があります。フルネームのフィールドを取得して、ファーストネーム、ミドルネーム、ラストネームに分割できるようにしたいと思います。

データにはプレフィックスやサフィックスは含まれません。ミドルネームはオプションです。データのフォーマットは「First Middle Last」です。

90% 達成するための実用的な解決策に興味があります。前述のとおり、これは複雑な問題なので、特殊なケースについては個別に処理します。

4

24 に答える 24

138

これは、簡単に操作できるテストデータを使用した自己完結型の例です。

この例では、3つ以上の部分からなる名前がある場合、すべての「余分な」ものがLAST_NAMEフィールドに入れられます。「DR」、「MRS」、「MR」など、「タイトル」として識別される特定の文字列には例外があります。

ミドルネームが欠落している場合は、FIRST_NAMEとLAST_NAMEを取得するだけです(MIDDLE_NAMEはNULLになります)。

それをSUBSTRINGの巨大なネストされたブロブに粉砕することもできますが、SQLでこれを行う場合と同様に、読みやすさは十分に困難です。

編集-次の特殊なケースを処理します。

1-NAMEフィールドがNULLです

2-NAMEフィールドには先頭/末尾のスペースが含まれます

3-NAMEフィールドの名前内に1つ以上の連続したスペースがあります

4-NAMEフィールドには名のみが含まれます

5-読みやすくするために、元のフルネームを別の列として最終出力に含めます

6-プレフィックスの特定のリストを個別の「タイトル」列として処理します

SELECT
  FIRST_NAME.ORIGINAL_INPUT_DATA
 ,FIRST_NAME.TITLE
 ,FIRST_NAME.FIRST_NAME
 ,CASE WHEN 0 = CHARINDEX(' ',FIRST_NAME.REST_OF_NAME)
       THEN NULL  --no more spaces?  assume rest is the last name
       ELSE SUBSTRING(
                       FIRST_NAME.REST_OF_NAME
                      ,1
                      ,CHARINDEX(' ',FIRST_NAME.REST_OF_NAME)-1
                     )
       END AS MIDDLE_NAME
 ,SUBSTRING(
             FIRST_NAME.REST_OF_NAME
            ,1 + CHARINDEX(' ',FIRST_NAME.REST_OF_NAME)
            ,LEN(FIRST_NAME.REST_OF_NAME)
           ) AS LAST_NAME
FROM
  (  
  SELECT
    TITLE.TITLE
   ,CASE WHEN 0 = CHARINDEX(' ',TITLE.REST_OF_NAME)
         THEN TITLE.REST_OF_NAME --No space? return the whole thing
         ELSE SUBSTRING(
                         TITLE.REST_OF_NAME
                        ,1
                        ,CHARINDEX(' ',TITLE.REST_OF_NAME)-1
                       )
    END AS FIRST_NAME
   ,CASE WHEN 0 = CHARINDEX(' ',TITLE.REST_OF_NAME)  
         THEN NULL  --no spaces @ all?  then 1st name is all we have
         ELSE SUBSTRING(
                         TITLE.REST_OF_NAME
                        ,CHARINDEX(' ',TITLE.REST_OF_NAME)+1
                        ,LEN(TITLE.REST_OF_NAME)
                       )
    END AS REST_OF_NAME
   ,TITLE.ORIGINAL_INPUT_DATA
  FROM
    (   
    SELECT
      --if the first three characters are in this list,
      --then pull it as a "title".  otherwise return NULL for title.
      CASE WHEN SUBSTRING(TEST_DATA.FULL_NAME,1,3) IN ('MR ','MS ','DR ','MRS')
           THEN LTRIM(RTRIM(SUBSTRING(TEST_DATA.FULL_NAME,1,3)))
           ELSE NULL
           END AS TITLE
      --if you change the list, don't forget to change it here, too.
      --so much for the DRY prinicple...
     ,CASE WHEN SUBSTRING(TEST_DATA.FULL_NAME,1,3) IN ('MR ','MS ','DR ','MRS')
           THEN LTRIM(RTRIM(SUBSTRING(TEST_DATA.FULL_NAME,4,LEN(TEST_DATA.FULL_NAME))))
           ELSE LTRIM(RTRIM(TEST_DATA.FULL_NAME))
           END AS REST_OF_NAME
     ,TEST_DATA.ORIGINAL_INPUT_DATA
    FROM
      (
      SELECT
        --trim leading & trailing spaces before trying to process
        --disallow extra spaces *within* the name
        REPLACE(REPLACE(LTRIM(RTRIM(FULL_NAME)),'  ',' '),'  ',' ') AS FULL_NAME
       ,FULL_NAME AS ORIGINAL_INPUT_DATA
      FROM
        (
        --if you use this, then replace the following
        --block with your actual table
              SELECT 'GEORGE W BUSH' AS FULL_NAME
        UNION SELECT 'SUSAN B ANTHONY' AS FULL_NAME
        UNION SELECT 'ALEXANDER HAMILTON' AS FULL_NAME
        UNION SELECT 'OSAMA BIN LADEN JR' AS FULL_NAME
        UNION SELECT 'MARTIN J VAN BUREN SENIOR III' AS FULL_NAME
        UNION SELECT 'TOMMY' AS FULL_NAME
        UNION SELECT 'BILLY' AS FULL_NAME
        UNION SELECT NULL AS FULL_NAME
        UNION SELECT ' ' AS FULL_NAME
        UNION SELECT '    JOHN  JACOB     SMITH' AS FULL_NAME
        UNION SELECT ' DR  SANJAY       GUPTA' AS FULL_NAME
        UNION SELECT 'DR JOHN S HOPKINS' AS FULL_NAME
        UNION SELECT ' MRS  SUSAN ADAMS' AS FULL_NAME
        UNION SELECT ' MS AUGUSTA  ADA   KING ' AS FULL_NAME      
        ) RAW_DATA
      ) TEST_DATA
    ) TITLE
  ) FIRST_NAME
于 2008-10-01T21:08:45.503 に答える
9

「フルネーム」がどのようにフォーマットされているかを知らずに答えるのは難しいです.

「姓、名のミドルネーム」または「名のミドルネームの姓」などです。

基本的に、SUBSTRING関数を使用する必要があります。

SUBSTRING ( expression , start , length )

そしておそらくCHARINDEX関数

CHARINDEX (substr, expression)

抽出する各部分の開始点と長さを把握します。

したがって、形式が「姓名」であるとしましょう(テストされていませんが、近いはずです):

SELECT 
SUBSTRING(fullname, 1, CHARINDEX(' ', fullname) - 1) AS FirstName, 
SUBSTRING(fullname, CHARINDEX(' ', fullname) + 1, len(fullname)) AS LastName
FROM YourTable
于 2008-10-01T20:46:17.697 に答える
8

問題を逆にして、列を追加して個々のピースを保持し、それらを組み合わせて完全な名前を取得します。

これが最良の答えになる理由は、人が自分の名前として登録されていること、およびミドルネームが何であるかを把握する保証された方法がないためです.

たとえば、これをどのように分割しますか。

Jan Olav Olsen Heggelien

これは架空のものですが、ノルウェーでは正式な名前であり、次のように分割することもできますが、分割する必要はありません。

First name: Jan Olav
Middle name: Olsen
Last name: Heggelien

または、次のように:

First name: Jan Olav
Last name: Olsen Heggelien

または、次のように:

First name: Jan
Middle name: Olav
Last name: Olsen Heggelien

ほとんどの言語で同様の現象が見られると思います。

そのため、正しく解釈するのに十分な情報を持たないデータを解釈しようとする代わりに、正しい解釈を保存し、結合して完全な名前を取得します。

于 2008-10-01T20:50:32.867 に答える
8

別の簡単な方法は、次を使用することparsenameです。

select full_name,
   parsename(replace(full_name, ' ', '.'), 3) as FirstName,
   parsename(replace(full_name, ' ', '.'), 2) as MiddleName,
   parsename(replace(full_name, ' ', '.'), 1) as LastName 
from YourTableName

ソース

于 2015-12-29T08:31:21.320 に答える
7

非常に適切に動作するデータがない限り、これは重要な課題です。単純なアプローチは、空白でトークン化し、3 つのトークンの結果が [最初、中間、最後] であり、2 つのトークンの結果が [最初、最後] であると想定することですが、複数のトークンに対処する必要があります。単語の姓 (例: "Van Buren") と複数のミドル ネーム。

于 2008-10-01T20:40:28.193 に答える
2

正式な正式名には常に姓、名、ミドルネームが含まれますか? 私は、本名が 1 つしかない人を知っていますが、正直なところ、それがファースト ネームかラスト ネームかはわかりません。:-) 私はまた、本名に複数のファースト ネームを持っているが、ミドル ネームを持っていない人を知っています。また、複数のミドルネームを持っている人もいます。

次に、完全な正式名の名前の順序もあります。私の知る限り、一部のアジアの文化では、姓が正式な正式名の最初に来ます。

より実用的なメモでは、フルネームを空白で分割し、最初のトークンを名として、最後のトークン (または名前が 1 つしかない場合は唯一のトークン) を姓として脅かすことができます。ただし、これは順序が常に同じであることを前提としています。

于 2008-10-01T20:43:44.877 に答える
1

PHP で人間の名前を解析しようとしている場合は、Keith Beckman の nameparse.php scriptをお勧めします。

サイトがダウンした場合のコピー:

<?
/*
Name:   nameparse.php
Version: 0.2a
Date:   030507
First:  030407
License:    GNU General Public License v2
Bugs:   If one of the words in the middle name is Ben (or St., for that matter),
        or any other possible last-name prefix, the name MUST be entered in
        last-name-first format. If the last-name parsing routines get ahold
        of any prefix, they tie up the rest of the name up to the suffix. i.e.:

        William Ben Carey   would yield 'Ben Carey' as the last name, while,
        Carey, William Ben  would yield 'Carey' as last and 'Ben' as middle.

        This is a problem inherent in the prefix-parsing routines algorithm,
        and probably will not be fixed. It's not my fault that there's some
        odd overlap between various languages. Just don't name your kids
        'Something Ben Something', and you should be alright.

*/

function    norm_str($string) {
    return  trim(strtolower(
        str_replace('.','',$string)));
    }

function    in_array_norm($needle,$haystack) {
    return  in_array(norm_str($needle),$haystack);
    }

function    parse_name($fullname) {
    $titles         =   array('dr','miss','mr','mrs','ms','judge');
    $prefices       =   array('ben','bin','da','dal','de','del','der','de','e',
                            'la','le','san','st','ste','van','vel','von');
    $suffices       =   array('esq','esquire','jr','sr','2','ii','iii','iv');

    $pieces         =   explode(',',preg_replace('/\s+/',' ',trim($fullname)));
    $n_pieces       =   count($pieces);

    switch($n_pieces) {
        case    1:  // array(title first middles last suffix)
            $subp   =   explode(' ',trim($pieces[0]));
            $n_subp =   count($subp);
            for($i = 0; $i < $n_subp; $i++) {
                $curr               =   trim($subp[$i]);
                $next               =   trim($subp[$i+1]);

                if($i == 0 && in_array_norm($curr,$titles)) {
                    $out['title']   =   $curr;
                    continue;
                    }

                if(!$out['first']) {
                    $out['first']   =   $curr;
                    continue;
                    }

                if($i == $n_subp-2 && $next && in_array_norm($next,$suffices)) {
                    if($out['last']) {
                        $out['last']    .=  " $curr";
                        }
                    else {
                        $out['last']    =   $curr;
                        }
                    $out['suffix']      =   $next;
                    break;
                    }

                if($i == $n_subp-1) {
                    if($out['last']) {
                        $out['last']    .=  " $curr";
                        }
                    else {
                        $out['last']    =   $curr;
                        }
                    continue;
                    }

                if(in_array_norm($curr,$prefices)) {
                    if($out['last']) {
                        $out['last']    .=  " $curr";
                        }
                    else {
                        $out['last']    =   $curr;
                        }
                    continue;
                    }

                if($next == 'y' || $next == 'Y') {
                    if($out['last']) {
                        $out['last']    .=  " $curr";
                        }
                    else {
                        $out['last']    =   $curr;
                        }
                    continue;
                    }

                if($out['last']) {
                    $out['last']    .=  " $curr";
                    continue;
                    }

                if($out['middle']) {
                    $out['middle']      .=  " $curr";
                    }
                else {
                    $out['middle']      =   $curr;
                    }
                }
            break;
        case    2:
                switch(in_array_norm($pieces[1],$suffices)) {
                    case    TRUE: // array(title first middles last,suffix)
                        $subp   =   explode(' ',trim($pieces[0]));
                        $n_subp =   count($subp);
                        for($i = 0; $i < $n_subp; $i++) {
                            $curr               =   trim($subp[$i]);
                            $next               =   trim($subp[$i+1]);

                            if($i == 0 && in_array_norm($curr,$titles)) {
                                $out['title']   =   $curr;
                                continue;
                                }

                            if(!$out['first']) {
                                $out['first']   =   $curr;
                                continue;
                                }

                            if($i == $n_subp-1) {
                                if($out['last']) {
                                    $out['last']    .=  " $curr";
                                    }
                                else {
                                    $out['last']    =   $curr;
                                    }
                                continue;
                                }

                            if(in_array_norm($curr,$prefices)) {
                                if($out['last']) {
                                    $out['last']    .=  " $curr";
                                    }
                                else {
                                    $out['last']    =   $curr;
                                    }
                                continue;
                                }

                            if($next == 'y' || $next == 'Y') {
                                if($out['last']) {
                                    $out['last']    .=  " $curr";
                                    }
                                else {
                                    $out['last']    =   $curr;
                                    }
                                continue;
                                }

                            if($out['last']) {
                                $out['last']    .=  " $curr";
                                continue;
                                }

                            if($out['middle']) {
                                $out['middle']      .=  " $curr";
                                }
                            else {
                                $out['middle']      =   $curr;
                                }
                            }                       
                        $out['suffix']  =   trim($pieces[1]);
                        break;
                    case    FALSE: // array(last,title first middles suffix)
                        $subp   =   explode(' ',trim($pieces[1]));
                        $n_subp =   count($subp);
                        for($i = 0; $i < $n_subp; $i++) {
                            $curr               =   trim($subp[$i]);
                            $next               =   trim($subp[$i+1]);

                            if($i == 0 && in_array_norm($curr,$titles)) {
                                $out['title']   =   $curr;
                                continue;
                                }

                            if(!$out['first']) {
                                $out['first']   =   $curr;
                                continue;
                                }

                        if($i == $n_subp-2 && $next &&
                            in_array_norm($next,$suffices)) {
                            if($out['middle']) {
                                $out['middle']  .=  " $curr";
                                }
                            else {
                                $out['middle']  =   $curr;
                                }
                            $out['suffix']      =   $next;
                            break;
                            }

                        if($i == $n_subp-1 && in_array_norm($curr,$suffices)) {
                            $out['suffix']      =   $curr;
                            continue;
                            }

                        if($out['middle']) {
                            $out['middle']      .=  " $curr";
                            }
                        else {
                            $out['middle']      =   $curr;
                            }
                        }
                        $out['last']    =   $pieces[0];
                        break;
                    }
            unset($pieces);
            break;
        case    3:  // array(last,title first middles,suffix)
            $subp   =   explode(' ',trim($pieces[1]));
            $n_subp =   count($subp);
            for($i = 0; $i < $n_subp; $i++) {
                $curr               =   trim($subp[$i]);
                $next               =   trim($subp[$i+1]);
                if($i == 0 && in_array_norm($curr,$titles)) {
                    $out['title']   =   $curr;
                    continue;
                    }

                if(!$out['first']) {
                    $out['first']   =   $curr;
                    continue;
                    }

                if($out['middle']) {
                    $out['middle']      .=  " $curr";
                    }
                else {
                    $out['middle']      =   $curr;
                    }
                }

            $out['last']                =   trim($pieces[0]);
            $out['suffix']              =   trim($pieces[2]);
            break;
        default:    // unparseable
            unset($pieces);
            break;
        }

    return $out;
    }


?>
于 2009-11-01T02:32:31.913 に答える
1

これを反復プロセスとして行います。

1) テーブルをフラット ファイルにダンプして作業します。

2) スペースを区切り文字として使用して名前を分割する簡単なプログラムを作成します。最初のトークンが名前で、トークンが 3 つある場合はトークン 2 がミドル ネーム、トークン 3 が姓です。2 つのトークンがある場合、2 番目のトークンは姓です。(Perl、Java、C/C++、言語は問いません)

3) 結果を目で確認します。このルールに当てはまらない名前を探します。

4) その例を使用して、その例外を処理する新しいルールを作成します...

5) すすぎと繰り返し

最終的に、すべてのデータを修正するプログラムを入手できます。

于 2008-10-01T21:04:30.600 に答える
1

#1が言ったように、それは簡単ではありません。ハイフンでつながれた姓、イニシャル、二重名、名前の逆順、およびその他のさまざまな異常により、慎重に作成された機能が台無しになる可能性があります。

サードパーティのライブラリを使用できます (プラグ/免責事項 - 私はこの製品に取り組みました):

http://www.melissadata.com/nameobject/nameobject.htm

于 2008-10-01T20:59:08.647 に答える
0

他の誰もが言うように、単純なプログラム的な方法からはできません。

次の例を検討してください。

  • 大統領「ジョージ・ハーバート・ウォーカー・ブッシュ」(ファーストミドルミドルラスト)

  • 大統領暗殺者「ジョンウィルクスブース」(ファーストミドルラスト)

  • ギタリスト「EddieVanHalen」(ファースト・ラスト・ラスト)

  • そして彼のお母さんはおそらく彼をエドワード・ロデワイク・ヴァン・ヘイレン(最初のミドル最後の最後)と呼んでいます

  • 有名な漂流者「メアリー・アン・サマーズ」(ファースト・ファースト・ラスト)

  • ニューメキシコ州共和党議長「フェルナンドCデバカ」(最初最後最後最後)

于 2008-10-01T22:22:31.897 に答える
0

私がこれを行うのに遭遇した最大の問題は、「Bob R. Smith、Jr.」のようなケースでした。私が使用したアルゴリズムは、http://www.blackbeltcoder.com/Articles/strings/splitting-a-name-into-first-and-last-namesに掲載されています。私のコードはC#ですが、SQLである必要がある場合は移植できます。

于 2011-01-28T22:19:33.963 に答える
0

私はかつて、任意の文字列から名、姓、ミドルネームを解析するために500文字の正規表現を作成しました。その正規表現を使用しても、入力の完全な不整合のために、約97%の精度しか得られませんでした。それでも、何もないよりはましです。

于 2008-10-01T21:09:48.653 に答える
0

名前のスペースやその他の異常に関してすでに提起されている警告を条件として、次のコードは少なくとも名前の98%を処理します。(注:使用するデータベースに正規表現オプションがないため、SQLが乱雑になります。)

**警告:乱雑なSQLは次のとおりです:

create table parsname (fullname char(50), name1 char(30), name2 char(30), name3 char(30), name4 char(40));
insert into parsname (fullname) select fullname from ImportTable;
update parsname set name1 = substring(fullname, 1, locate(' ', fullname)),
 fullname = ltrim(substring(fullname, locate(' ', fullname), length(fullname)))
 where locate(' ', rtrim(fullname)) > 0;
update parsname set name2 = substring(fullname, 1, locate(' ', fullname)),
 fullname = ltrim(substring(fullname, locate(' ', fullname), length(fullname)))
 where locate(' ', rtrim(fullname)) > 0;
update parsname set name3 = substring(fullname, 1, locate(' ', fullname)),
 fullname = ltrim(substring(fullname, locate(' ', fullname), length(fullname)))
 where locate(' ', rtrim(fullname)) > 0;
update parsname set name4 = substring(fullname, 1, locate(' ', fullname)),
 fullname = ltrim(substring(fullname, locate(' ', fullname), length(fullname)))
 where locate(' ', rtrim(fullname)) > 0;
// fullname now contains the last word in the string.
select fullname as FirstName, '' as MiddleName, '' as LastName from parsname where fullname is not null and name1 is null and name2 is null
union all
select name1 as FirstName, name2 as MiddleName, fullname as LastName from parsname where name1 is not null and name3 is null

このコードは、一時テーブル(parsname)を作成し、フルネームをスペースでトークン化することで機能します。name3またはname4の値で終わる名前は不適合であり、別の方法で処理する必要があります。

于 2008-10-01T21:10:08.450 に答える
0

もちろん、この問題を解決する完璧な方法はないことを私たちは皆理解していますが、いくつかの解決策は他の解決策よりもあなたを遠ざけることができます。

特に、一般的なプレフィックス(Mr、Dr、Mrsなど)、インフィックス(von、de、delなど)、サフィックス(Jr、III)のリストがある場合は、単純な空白を超えるのは非常に簡単です。 、Srなど)など。また、一般的な名のリストがある場合(名前が多様な場合は、さまざまな言語/文化で)、真ん中の単語が家系の名前の一部である可能性が高いかどうかを推測できるので便利です。

BibTeXは、そこへの道の一部となるいくつかのヒューリスティックも実装しています。Text::BibTeX::Nameそれらはperlモジュールにカプセル化されています。これは、妥当な仕事をする簡単なコードサンプルです。

use Text::BibTeX;
use Text::BibTeX::Name;
$name = "Dr. Mario Luis de Luigi Jr.";
$name =~ s/^\s*([dm]rs?.?|miss)\s+//i;
$dr=$1;
$n=Text::BibTeX::Name->new($name);
print join("\t", $dr, map "@{[ $n->part($_) ]}", qw(first von last jr)), "\n";
于 2009-09-11T04:34:23.623 に答える
0

次のストアド プロシージャは、見つかった最初の単語を First Name に、最後の単語を Last Name に、その間のすべての単語を Middle Name に格納します。

create procedure [dbo].[import_ParseName]
(            
    @FullName nvarchar(max),
    @FirstName nvarchar(255) output,
    @MiddleName nvarchar(255) output,
    @LastName nvarchar(255)  output
)
as
begin

set @FirstName = ''
set @MiddleName = ''
set @LastName = ''  
set @FullName = ltrim(rtrim(@FullName))

declare @ReverseFullName nvarchar(max)
set @ReverseFullName = reverse(@FullName)

declare @lengthOfFullName int
declare @endOfFirstName int
declare @beginningOfLastName int

set @lengthOfFullName = len(@FullName)
set @endOfFirstName = charindex(' ', @FullName)
set @beginningOfLastName = @lengthOfFullName - charindex(' ', @ReverseFullName) + 1

set @FirstName = case when @endOfFirstName <> 0 
                      then substring(@FullName, 1, @endOfFirstName - 1) 
                      else ''
                 end

set @MiddleName = case when (@endOfFirstName <> 0 and @beginningOfLastName <> 0 and @beginningOfLastName > @endOfFirstName)
                       then ltrim(rtrim(substring(@FullName, @endOfFirstName , @beginningOfLastName - @endOfFirstName))) 
                       else ''
                  end

set @LastName = case when @beginningOfLastName <> 0 
                     then substring(@FullName, @beginningOfLastName + 1 , @lengthOfFullName - @beginningOfLastName)
                     else ''
                end

return

end 

そして、ここで私はそれを呼んでいます。

DECLARE @FirstName nvarchar(255),
        @MiddleName nvarchar(255),
        @LastName nvarchar(255)

EXEC    [dbo].[import_ParseName]
        @FullName = N'Scott The Other Scott Kowalczyk',
        @FirstName = @FirstName OUTPUT,
        @MiddleName = @MiddleName OUTPUT,
        @LastName = @LastName OUTPUT

print   @FirstName 
print   @MiddleName
print   @LastName 

output:

Scott
The Other Scott
Kowalczyk
于 2008-10-01T22:07:24.273 に答える
0
  1. SQL 正規表現関数を取得します。サンプル: http://msdn.microsoft.com/en-us/magazine/cc163473.aspx
  2. 正規表現を使用して名前を抽出します。

正規表現の学習/構築/テストには Expresso をお勧めします。旧無料版新商用版

于 2008-10-01T20:46:14.297 に答える
0

SQLサーバーについてはわかりませんが、postgresでは次のようなことができます:

SELECT 
  SUBSTRING(fullname, '(\\w+)') as firstname,
  SUBSTRING(fullname, '\\w+\\s(\\w+)\\s\\w+') as middle,
  COALESCE(SUBSTRING(fullname, '\\w+\\s\\w+\\s(\\w+)'), SUBSTRING(fullname, '\\w+\\s(\\w+)')) as lastname
FROM 
public.person

正規表現はおそらくもう少し簡潔になる可能性があります。しかし、あなたは要点を理解します。ちなみに、これは 2 つの二重名を持つ人には機能しないので (オランダでは「Jan van der Ploeg」が多い)、結果には非常に注意が必要です。

于 2008-10-01T20:52:55.387 に答える